nss: upgrade to release 3.73
[LibreOffice.git] / vcl / source / window / window.cxx
blob5e079161e492d63f0fc5e37534197bebfe231e8c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <rtl/strbuf.hxx>
21 #include <sal/log.hxx>
23 #include <sal/types.h>
24 #include <tools/diagnose_ex.h>
25 #include <vcl/salgtype.hxx>
26 #include <vcl/event.hxx>
27 #include <vcl/help.hxx>
28 #include <vcl/cursor.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/transfer.hxx>
31 #include <vcl/vclevent.hxx>
32 #include <vcl/window.hxx>
33 #include <vcl/syswin.hxx>
34 #include <vcl/dockwin.hxx>
35 #include <vcl/wall.hxx>
36 #include <vcl/toolkit/fixed.hxx>
37 #include <vcl/taskpanelist.hxx>
38 #include <vcl/toolkit/unowrap.hxx>
39 #include <vcl/lazydelete.hxx>
40 #include <vcl/virdev.hxx>
41 #include <vcl/settings.hxx>
42 #include <vcl/sysdata.hxx>
43 #include <vcl/ptrstyle.hxx>
44 #include <vcl/IDialogRenderable.hxx>
46 #include <vcl/uitest/uiobject.hxx>
48 #include <salframe.hxx>
49 #include <salobj.hxx>
50 #include <salinst.hxx>
51 #include <salgdi.hxx>
52 #include <svdata.hxx>
53 #include <window.h>
54 #include <toolbox.h>
55 #include <outdev.h>
56 #include <brdwin.hxx>
57 #include <helpwin.hxx>
59 #include <com/sun/star/accessibility/AccessibleRelation.hpp>
60 #include <com/sun/star/accessibility/XAccessible.hpp>
61 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
62 #include <com/sun/star/awt/XWindowPeer.hpp>
63 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
64 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
65 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
66 #include <com/sun/star/rendering/CanvasFactory.hpp>
67 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
68 #include <comphelper/lok.hxx>
69 #include <comphelper/processfactory.hxx>
70 #include <unotools/configmgr.hxx>
71 #include <osl/diagnose.h>
72 #include <tools/debug.hxx>
73 #include <tools/json_writer.hxx>
74 #include <boost/property_tree/ptree.hpp>
76 #include <cassert>
77 #include <typeinfo>
79 #ifdef _WIN32 // see #140456#
80 #include <win/salframe.h>
81 #endif
84 using namespace ::com::sun::star::uno;
85 using namespace ::com::sun::star::lang;
86 using namespace ::com::sun::star::datatransfer::clipboard;
87 using namespace ::com::sun::star::datatransfer::dnd;
89 namespace vcl {
91 Window::Window( WindowType nType )
92 : OutputDevice(OUTDEV_WINDOW)
93 , mpWindowImpl(new WindowImpl( nType ))
95 // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
96 mbEnableRTL = AllSettings::GetLayoutRTL();
99 Window::Window( vcl::Window* pParent, WinBits nStyle )
100 : OutputDevice(OUTDEV_WINDOW)
101 , mpWindowImpl(new WindowImpl( WindowType::WINDOW ))
103 // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
104 mbEnableRTL = AllSettings::GetLayoutRTL();
106 ImplInit( pParent, nStyle, nullptr );
109 #if OSL_DEBUG_LEVEL > 0
110 namespace
112 OString lcl_createWindowInfo(const vcl::Window* pWindow)
114 // skip border windows, they do not carry information that
115 // would help with diagnosing the problem
116 const vcl::Window* pTempWin( pWindow );
117 while ( pTempWin && pTempWin->GetType() == WindowType::BORDERWINDOW ) {
118 pTempWin = pTempWin->GetWindow( GetWindowType::FirstChild );
120 // check if pTempWin is not null, otherwise use the
121 // original address
122 if ( pTempWin ) {
123 pWindow = pTempWin;
126 OStringBuffer aErrorString;
127 aErrorString.append(' ');
128 aErrorString.append(typeid( *pWindow ).name());
129 aErrorString.append("(");
130 aErrorString.append(
131 OUStringToOString(
132 pWindow->GetText(),
133 RTL_TEXTENCODING_UTF8
136 aErrorString.append(")");
137 return aErrorString.makeStringAndClear();
140 #endif
142 bool Window::IsDisposed() const
144 return !mpWindowImpl;
147 void Window::dispose()
149 assert( mpWindowImpl );
150 assert( !mpWindowImpl->mbInDispose ); // should only be called from disposeOnce()
151 assert( (!mpWindowImpl->mpParent ||
152 !mpWindowImpl->mpParent->IsDisposed()) &&
153 "vcl::Window child should have its parent disposed first" );
155 // remove Key and Mouse events issued by Application::PostKey/MouseEvent
156 Application::RemoveMouseAndKeyEvents( this );
158 // Dispose of the canvas implementation (which, currently, has an
159 // own wrapper window as a child to this one.
160 Reference< css::rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
161 if( xCanvas.is() )
163 Reference < XComponent > xCanvasComponent( xCanvas, UNO_QUERY );
164 if( xCanvasComponent.is() )
165 xCanvasComponent->dispose();
168 mpWindowImpl->mbInDispose = true;
170 CallEventListeners( VclEventId::ObjectDying );
172 // do not send child events for frames that were registered as native frames
173 if( !ImplIsAccessibleNativeFrame() && mpWindowImpl->mbReallyVisible )
174 if ( ImplIsAccessibleCandidate() && GetAccessibleParentWindow() )
175 GetAccessibleParentWindow()->CallEventListeners( VclEventId::WindowChildDestroyed, this );
177 // remove associated data structures from dockingmanager
178 ImplGetDockingManager()->RemoveWindow( this );
180 // remove ownerdraw decorated windows from list in the top-most frame window
181 if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
183 ::std::vector< VclPtr<vcl::Window> >& rList = ImplGetOwnerDrawList();
184 auto p = ::std::find( rList.begin(), rList.end(), VclPtr<vcl::Window>(this) );
185 if( p != rList.end() )
186 rList.erase( p );
189 // shutdown drag and drop
190 Reference < XComponent > xDnDComponent( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY );
192 if( xDnDComponent.is() )
193 xDnDComponent->dispose();
195 if( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
199 // deregister drop target listener
200 if( mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
202 Reference< XDragGestureRecognizer > xDragGestureRecognizer(mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
203 if( xDragGestureRecognizer.is() )
205 xDragGestureRecognizer->removeDragGestureListener(
206 Reference< XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY));
209 mpWindowImpl->mpFrameData->mxDropTarget->removeDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
210 mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
213 // shutdown drag and drop for this frame window
214 Reference< XComponent > xComponent( mpWindowImpl->mpFrameData->mxDropTarget, UNO_QUERY );
216 // DNDEventDispatcher does not hold a reference of the DropTarget,
217 // so it's ok if it does not support XComponent
218 if( xComponent.is() )
219 xComponent->dispose();
221 catch (const Exception&)
223 // can be safely ignored here.
227 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper( false );
228 if ( pWrapper )
229 pWrapper->WindowDestroyed( this );
231 // MT: Must be called after WindowDestroyed!
232 // Otherwise, if the accessible is a VCLXWindow, it will try to destroy this window again!
233 // But accessibility implementations from applications need this dispose.
234 if ( mpWindowImpl->mxAccessible.is() )
236 Reference< XComponent> xC( mpWindowImpl->mxAccessible, UNO_QUERY );
237 if ( xC.is() )
238 xC->dispose();
241 ImplSVData* pSVData = ImplGetSVData();
243 if ( ImplGetSVHelpData().mpHelpWin && (ImplGetSVHelpData().mpHelpWin->GetParent() == this) )
244 ImplDestroyHelpWindow( true );
246 SAL_WARN_IF(pSVData->mpWinData->mpTrackWin.get() == this, "vcl.window",
247 "Window::~Window(): Window is in TrackingMode");
248 SAL_WARN_IF(IsMouseCaptured(), "vcl.window",
249 "Window::~Window(): Window has the mouse captured");
251 // due to old compatibility
252 if (pSVData->mpWinData->mpTrackWin == this)
253 EndTracking();
254 if (IsMouseCaptured())
255 ReleaseMouse();
257 #if OSL_DEBUG_LEVEL > 0
258 // always perform these tests in debug builds
260 OStringBuffer aErrorStr;
261 bool bError = false;
262 vcl::Window* pTempWin;
264 if ( mpWindowImpl->mpFirstChild )
266 OStringBuffer aTempStr("Window (");
267 aTempStr.append(lcl_createWindowInfo(this));
268 aTempStr.append(") with live children destroyed: ");
269 pTempWin = mpWindowImpl->mpFirstChild;
270 while ( pTempWin )
272 aTempStr.append(lcl_createWindowInfo(pTempWin));
273 pTempWin = pTempWin->mpWindowImpl->mpNext;
275 OSL_FAIL( aTempStr.getStr() );
276 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
279 if (mpWindowImpl->mpFrameData != nullptr)
281 pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap;
282 while ( pTempWin )
284 if ( ImplIsRealParentPath( pTempWin ) )
286 bError = true;
287 aErrorStr.append(lcl_createWindowInfo(pTempWin));
289 pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
291 if ( bError )
293 OStringBuffer aTempStr;
294 aTempStr.append("Window (");
295 aTempStr.append(lcl_createWindowInfo(this));
296 aTempStr.append(") with live SystemWindows destroyed: ");
297 aTempStr.append(aErrorStr.toString());
298 OSL_FAIL(aTempStr.getStr());
299 // abort in debug builds, must be fixed!
300 Application::Abort(OStringToOUString(
301 aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
305 bError = false;
306 pTempWin = pSVData->maFrameData.mpFirstFrame;
307 while ( pTempWin )
309 if ( ImplIsRealParentPath( pTempWin ) )
311 bError = true;
312 aErrorStr.append(lcl_createWindowInfo(pTempWin));
314 pTempWin = pTempWin->mpWindowImpl->mpFrameData->mpNextFrame;
316 if ( bError )
318 OStringBuffer aTempStr( "Window (" );
319 aTempStr.append(lcl_createWindowInfo(this));
320 aTempStr.append(") with live SystemWindows destroyed: ");
321 aTempStr.append(aErrorStr.toString());
322 OSL_FAIL( aTempStr.getStr() );
323 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
326 if ( mpWindowImpl->mpFirstOverlap )
328 OStringBuffer aTempStr("Window (");
329 aTempStr.append(lcl_createWindowInfo(this));
330 aTempStr.append(") with live SystemWindows destroyed: ");
331 pTempWin = mpWindowImpl->mpFirstOverlap;
332 while ( pTempWin )
334 aTempStr.append(lcl_createWindowInfo(pTempWin));
335 pTempWin = pTempWin->mpWindowImpl->mpNext;
337 OSL_FAIL( aTempStr.getStr() );
338 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
341 vcl::Window* pMyParent = GetParent();
342 SystemWindow* pMySysWin = nullptr;
344 while ( pMyParent )
346 if ( pMyParent->IsSystemWindow() )
348 pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
350 pMyParent = pMyParent->GetParent();
352 if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
354 OStringBuffer aTempStr("Window (");
355 aTempStr.append(lcl_createWindowInfo(this));
356 aTempStr.append(") still in TaskPanelList!");
357 OSL_FAIL( aTempStr.getStr() );
358 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
361 #endif
363 if( mpWindowImpl->mbIsInTaskPaneList )
365 vcl::Window* pMyParent = GetParent();
366 SystemWindow* pMySysWin = nullptr;
368 while ( pMyParent )
370 if ( pMyParent->IsSystemWindow() )
372 pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
374 pMyParent = pMyParent->GetParent();
376 if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
378 pMySysWin->GetTaskPaneList()->RemoveWindow( this );
380 else
382 SAL_WARN( "vcl", "Window (" << GetText() << ") not found in TaskPanelList");
386 // remove from size-group if necessary
387 remove_from_all_size_groups();
389 // clear mnemonic labels
390 std::vector<VclPtr<FixedText> > aMnemonicLabels(list_mnemonic_labels());
391 for (auto const& mnemonicLabel : aMnemonicLabels)
393 remove_mnemonic_label(mnemonicLabel);
396 // hide window in order to trigger the Paint-Handling
397 Hide();
399 // EndExtTextInputMode
400 if (pSVData->mpWinData->mpExtTextInputWin == this)
402 EndExtTextInput();
403 if (pSVData->mpWinData->mpExtTextInputWin == this)
404 pSVData->mpWinData->mpExtTextInputWin = nullptr;
407 // check if the focus window is our child
408 bool bHasFocusedChild = false;
409 if (pSVData->mpWinData->mpFocusWin && ImplIsRealParentPath(pSVData->mpWinData->mpFocusWin))
411 // #122232#, this must not happen and is an application bug ! but we try some cleanup to hopefully avoid crashes, see below
412 bHasFocusedChild = true;
413 #if OSL_DEBUG_LEVEL > 0
414 OUString aTempStr = "Window (" + GetText() +
415 ") with focused child window destroyed ! THIS WILL LEAD TO CRASHES AND MUST BE FIXED !";
416 SAL_WARN( "vcl", aTempStr );
417 Application::Abort(aTempStr); // abort in debug build version, this must be fixed!
418 #endif
421 // if we get focus pass focus to another window
422 vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow();
423 if (pSVData->mpWinData->mpFocusWin == this
424 || bHasFocusedChild) // #122232#, see above, try some cleanup
426 if ( mpWindowImpl->mbFrame )
428 pSVData->mpWinData->mpFocusWin = nullptr;
429 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
431 else
433 vcl::Window* pParent = GetParent();
434 vcl::Window* pBorderWindow = mpWindowImpl->mpBorderWindow;
435 // when windows overlap, give focus to the parent
436 // of the next FrameWindow
437 if ( pBorderWindow )
439 if ( pBorderWindow->ImplIsOverlapWindow() )
440 pParent = pBorderWindow->mpWindowImpl->mpOverlapWindow;
442 else if ( ImplIsOverlapWindow() )
443 pParent = mpWindowImpl->mpOverlapWindow;
445 if ( pParent && pParent->IsEnabled() && pParent->IsInputEnabled() && ! pParent->IsInModalMode() )
446 pParent->GrabFocus();
447 else
448 mpWindowImpl->mpFrameWindow->GrabFocus();
450 // If the focus was set back to 'this' set it to nothing
451 if (pSVData->mpWinData->mpFocusWin == this)
453 pSVData->mpWinData->mpFocusWin = nullptr;
454 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
459 if ( pOverlapWindow != nullptr &&
460 pOverlapWindow->mpWindowImpl->mpLastFocusWindow == this )
461 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
463 // reset hint for DefModalDialogParent
464 if( pSVData->maFrameData.mpActiveApplicationFrame == this )
465 pSVData->maFrameData.mpActiveApplicationFrame = nullptr;
467 // reset hint of what was the last wheeled window
468 if (pSVData->mpWinData->mpLastWheelWindow == this)
469 pSVData->mpWinData->mpLastWheelWindow = nullptr;
471 // reset marked windows
472 if ( mpWindowImpl->mpFrameData != nullptr )
474 if ( mpWindowImpl->mpFrameData->mpFocusWin == this )
475 mpWindowImpl->mpFrameData->mpFocusWin = nullptr;
476 if ( mpWindowImpl->mpFrameData->mpMouseMoveWin == this )
477 mpWindowImpl->mpFrameData->mpMouseMoveWin = nullptr;
478 if ( mpWindowImpl->mpFrameData->mpMouseDownWin == this )
479 mpWindowImpl->mpFrameData->mpMouseDownWin = nullptr;
482 // reset Deactivate-Window
483 if (pSVData->mpWinData->mpLastDeacWin == this)
484 pSVData->mpWinData->mpLastDeacWin = nullptr;
486 if ( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
488 if ( mpWindowImpl->mpFrameData->mnFocusId )
489 Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnFocusId );
490 mpWindowImpl->mpFrameData->mnFocusId = nullptr;
491 if ( mpWindowImpl->mpFrameData->mnMouseMoveId )
492 Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId );
493 mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
496 // release SalGraphics
497 OutputDevice *pOutDev = GetOutDev();
498 pOutDev->ReleaseGraphics();
500 // remove window from the lists
501 ImplRemoveWindow( true );
503 // de-register as "top window child" at our parent, if necessary
504 if ( mpWindowImpl->mbFrame )
506 bool bIsTopWindow
507 = mpWindowImpl->mpWinData && (mpWindowImpl->mpWinData->mnIsTopWindow == 1);
508 if ( mpWindowImpl->mpRealParent && bIsTopWindow )
510 ImplWinData* pParentWinData = mpWindowImpl->mpRealParent->ImplGetWinData();
512 auto myPos = ::std::find( pParentWinData->maTopWindowChildren.begin(),
513 pParentWinData->maTopWindowChildren.end(), VclPtr<vcl::Window>(this) );
514 SAL_WARN_IF( myPos == pParentWinData->maTopWindowChildren.end(), "vcl.window", "Window::~Window: inconsistency in top window chain!" );
515 if ( myPos != pParentWinData->maTopWindowChildren.end() )
516 pParentWinData->maTopWindowChildren.erase( myPos );
520 delete mpWindowImpl->mpWinData;
521 mpWindowImpl->mpWinData = nullptr;
523 // remove BorderWindow or Frame window data
524 mpWindowImpl->mpBorderWindow.disposeAndClear();
525 if ( mpWindowImpl->mbFrame )
527 if ( pSVData->maFrameData.mpFirstFrame == this )
528 pSVData->maFrameData.mpFirstFrame = mpWindowImpl->mpFrameData->mpNextFrame;
529 else
531 sal_Int32 nWindows = 0;
532 vcl::Window* pSysWin = pSVData->maFrameData.mpFirstFrame;
533 while ( pSysWin && pSysWin->mpWindowImpl->mpFrameData->mpNextFrame.get() != this )
535 pSysWin = pSysWin->mpWindowImpl->mpFrameData->mpNextFrame;
536 nWindows++;
539 if ( pSysWin )
541 assert (mpWindowImpl->mpFrameData->mpNextFrame.get() != pSysWin);
542 pSysWin->mpWindowImpl->mpFrameData->mpNextFrame = mpWindowImpl->mpFrameData->mpNextFrame;
544 else // if it is not in the list, we can't remove it.
545 SAL_WARN("vcl.window", "Window " << this << " marked as frame window, "
546 "is missing from list of " << nWindows << " frames");
548 if (mpWindowImpl->mpFrame) // otherwise exception during init
550 mpWindowImpl->mpFrame->SetCallback( nullptr, nullptr );
551 pSVData->mpDefInst->DestroyFrame( mpWindowImpl->mpFrame );
553 assert (mpWindowImpl->mpFrameData->mnFocusId == nullptr);
554 assert (mpWindowImpl->mpFrameData->mnMouseMoveId == nullptr);
556 mpWindowImpl->mpFrameData->mpBuffer.disposeAndClear();
557 delete mpWindowImpl->mpFrameData;
558 mpWindowImpl->mpFrameData = nullptr;
561 // should be the last statements
562 mpWindowImpl.reset();
564 OutputDevice::dispose();
567 Window::~Window()
569 disposeOnce();
572 // We will eventually being removing the inheritance of OutputDevice
573 // from Window. It will be replaced with a transient relationship such
574 // that the OutputDevice is only live for the scope of the Paint method.
575 // In the meantime this can help move us towards a Window use an
576 // OutputDevice, not being one.
578 ::OutputDevice const* Window::GetOutDev() const
580 return this;
583 ::OutputDevice* Window::GetOutDev()
585 return this;
588 Color Window::GetBackgroundColor() const
590 return GetDisplayBackground().GetColor();
593 } /* namespace vcl */
595 WindowImpl::WindowImpl( WindowType nType )
597 maZoom = Fraction( 1, 1 );
598 maWinRegion = vcl::Region(true);
599 maWinClipRegion = vcl::Region(true);
600 mpWinData = nullptr; // Extra Window Data, that we don't need for all windows
601 mpFrameData = nullptr; // Frame Data
602 mpFrame = nullptr; // Pointer to frame window
603 mpSysObj = nullptr;
604 mpFrameWindow = nullptr; // window to top level parent (same as frame window)
605 mpOverlapWindow = nullptr; // first overlap parent
606 mpBorderWindow = nullptr; // Border-Window
607 mpClientWindow = nullptr; // Client-Window of a FrameWindow
608 mpParent = nullptr; // parent (incl. BorderWindow)
609 mpRealParent = nullptr; // real parent (excl. BorderWindow)
610 mpFirstChild = nullptr; // first child window
611 mpLastChild = nullptr; // last child window
612 mpFirstOverlap = nullptr; // first overlap window (only set in overlap windows)
613 mpLastOverlap = nullptr; // last overlap window (only set in overlap windows)
614 mpPrev = nullptr; // prev window
615 mpNext = nullptr; // next window
616 mpNextOverlap = nullptr; // next overlap window of frame
617 mpLastFocusWindow = nullptr; // window for focus restore
618 mpDlgCtrlDownWindow = nullptr; // window for dialog control
619 mnEventListenersIteratingCount = 0;
620 mnChildEventListenersIteratingCount = 0;
621 mpCursor = nullptr; // cursor
622 maPointer = PointerStyle::Arrow;
623 mpVCLXWindow = nullptr;
624 mpAccessibleInfos = nullptr;
625 maControlForeground = COL_TRANSPARENT; // no foreground set
626 maControlBackground = COL_TRANSPARENT; // no background set
627 mnLeftBorder = 0; // left border
628 mnTopBorder = 0; // top border
629 mnRightBorder = 0; // right border
630 mnBottomBorder = 0; // bottom border
631 mnWidthRequest = -1; // width request
632 mnHeightRequest = -1; // height request
633 mnOptimalWidthCache = -1; // optimal width cache
634 mnOptimalHeightCache = -1; // optimal height cache
635 mnX = 0; // X-Position to Parent
636 mnY = 0; // Y-Position to Parent
637 mnAbsScreenX = 0; // absolute X-position on screen, used for RTL window positioning
638 mpChildClipRegion = nullptr; // Child-Clip-Region when ClipChildren
639 mpPaintRegion = nullptr; // Paint-ClipRegion
640 mnStyle = 0; // style (init in ImplInitWindow)
641 mnPrevStyle = 0; // prevstyle (set in SetStyle)
642 mnExtendedStyle = WindowExtendedStyle::NONE; // extended style (init in ImplInitWindow)
643 mnType = nType; // type
644 mnGetFocusFlags = GetFocusFlags::NONE; // Flags for GetFocus()-Call
645 mnWaitCount = 0; // Wait-Count (>1 == "wait" mouse pointer)
646 mnPaintFlags = ImplPaintFlags::NONE; // Flags for ImplCallPaint
647 mnParentClipMode = ParentClipMode::NONE; // Flags for Parent-ClipChildren-Mode
648 mnActivateMode = ActivateModeFlags::NONE; // Will be converted in System/Overlap-Windows
649 mnDlgCtrlFlags = DialogControlFlags::NONE; // DialogControl-Flags
650 meAlwaysInputMode = AlwaysInputNone; // AlwaysEnableInput not called
651 meHalign = VclAlign::Fill;
652 meValign = VclAlign::Fill;
653 mePackType = VclPackType::Start;
654 mnPadding = 0;
655 mnGridHeight = 1;
656 mnGridLeftAttach = -1;
657 mnGridTopAttach = -1;
658 mnGridWidth = 1;
659 mnBorderWidth = 0;
660 mnMarginLeft = 0;
661 mnMarginRight = 0;
662 mnMarginTop = 0;
663 mnMarginBottom = 0;
664 mbFrame = false; // true: Window is a frame window
665 mbBorderWin = false; // true: Window is a border window
666 mbOverlapWin = false; // true: Window is an overlap window
667 mbSysWin = false; // true: SystemWindow is the base class
668 mbDialog = false; // true: Dialog is the base class
669 mbDockWin = false; // true: DockingWindow is the base class
670 mbFloatWin = false; // true: FloatingWindow is the base class
671 mbPushButton = false; // true: PushButton is the base class
672 mbToolBox = false; // true: ToolBox is the base class
673 mbMenuFloatingWindow = false; // true: MenuFloatingWindow is the base class
674 mbToolbarFloatingWindow = false; // true: ImplPopupFloatWin is the base class, used for subtoolbars
675 mbSplitter = false; // true: Splitter is the base class
676 mbVisible = false; // true: Show( true ) called
677 mbOverlapVisible = false; // true: Hide called for visible window from ImplHideAllOverlapWindow()
678 mbDisabled = false; // true: Enable( false ) called
679 mbInputDisabled = false; // true: EnableInput( false ) called
680 mbNoUpdate = false; // true: SetUpdateMode( false ) called
681 mbNoParentUpdate = false; // true: SetParentUpdateMode( false ) called
682 mbActive = false; // true: Window Active
683 mbReallyVisible = false; // true: this and all parents to an overlapped window are visible
684 mbReallyShown = false; // true: this and all parents to an overlapped window are shown
685 mbInInitShow = false; // true: we are in InitShow
686 mbChildPtrOverwrite = false; // true: PointerStyle overwrites Child-Pointer
687 mbNoPtrVisible = false; // true: ShowPointer( false ) called
688 mbPaintFrame = false; // true: Paint is visible, but not painted
689 mbInPaint = false; // true: Inside PaintHdl
690 mbMouseButtonDown = false; // true: BaseMouseButtonDown called
691 mbMouseButtonUp = false; // true: BaseMouseButtonUp called
692 mbKeyInput = false; // true: BaseKeyInput called
693 mbKeyUp = false; // true: BaseKeyUp called
694 mbCommand = false; // true: BaseCommand called
695 mbDefPos = true; // true: Position is not Set
696 mbDefSize = true; // true: Size is not Set
697 mbCallMove = true; // true: Move must be called by Show
698 mbCallResize = true; // true: Resize must be called by Show
699 mbWaitSystemResize = true; // true: Wait for System-Resize
700 mbInitWinClipRegion = true; // true: Calc Window Clip Region
701 mbInitChildRegion = false; // true: InitChildClipRegion
702 mbWinRegion = false; // true: Window Region
703 mbClipChildren = false; // true: Child-window should be clipped
704 mbClipSiblings = false; // true: Adjacent Child-window should be clipped
705 mbChildTransparent = false; // true: Child-windows are allowed to switch to transparent (incl. Parent-CLIPCHILDREN)
706 mbPaintTransparent = false; // true: Paints should be executed on the Parent
707 mbMouseTransparent = false; // true: Window is transparent for Mouse
708 mbDlgCtrlStart = false; // true: From here on own Dialog-Control
709 mbFocusVisible = false; // true: Focus Visible
710 mbUseNativeFocus = false;
711 mbNativeFocusVisible = false; // true: native Focus Visible
712 mbInShowFocus = false; // prevent recursion
713 mbInHideFocus = false; // prevent recursion
714 mbTrackVisible = false; // true: Tracking Visible
715 mbControlForeground = false; // true: Foreground-Property set
716 mbControlBackground = false; // true: Background-Property set
717 mbAlwaysOnTop = false; // true: always visible for all others windows
718 mbCompoundControl = false; // true: Composite Control => Listener...
719 mbCompoundControlHasFocus = false; // true: Composite Control has focus somewhere
720 mbPaintDisabled = false; // true: Paint should not be executed
721 mbAllResize = false; // true: Also sent ResizeEvents with 0,0
722 mbInDispose = false; // true: We're still in Window::dispose()
723 mbExtTextInput = false; // true: ExtTextInput-Mode is active
724 mbInFocusHdl = false; // true: Within GetFocus-Handler
725 mbCreatedWithToolkit = false;
726 mbSuppressAccessibilityEvents = false; // true: do not send any accessibility events
727 mbDrawSelectionBackground = false; // true: draws transparent window background to indicate (toolbox) selection
728 mbIsInTaskPaneList = false; // true: window was added to the taskpanelist in the topmost system window
729 mnNativeBackground = ControlPart::NONE; // initialize later, depends on type
730 mbHelpTextDynamic = false; // true: append help id in HELP_DEBUG case
731 mbFakeFocusSet = false; // true: pretend as if the window has focus.
732 mbHexpand = false;
733 mbVexpand = false;
734 mbExpand = false;
735 mbFill = true;
736 mbSecondary = false;
737 mbNonHomogeneous = false;
738 static bool bDoubleBuffer = getenv("VCL_DOUBLEBUFFERING_FORCE_ENABLE");
739 mbDoubleBufferingRequested = bDoubleBuffer; // when we are not sure, assume it cannot do double-buffering via RenderContext
740 mpLOKNotifier = nullptr;
741 mnLOKWindowId = 0;
742 mbLOKParentNotifier = false;
745 WindowImpl::~WindowImpl()
747 mpChildClipRegion.reset();
748 mpAccessibleInfos.reset();
751 ImplWinData::ImplWinData() :
752 mnCursorExtWidth(0),
753 mbVertical(false),
754 mnCompositionCharRects(0),
755 mnTrackFlags(ShowTrackFlags::NONE),
756 mnIsTopWindow(sal_uInt16(~0)), // not initialized yet, 0/1 will indicate TopWindow (see IsTopWindow())
757 mbMouseOver(false),
758 mbEnableNativeWidget(false)
762 ImplWinData::~ImplWinData()
764 mpCompositionCharRects.reset();
767 ImplFrameData::ImplFrameData( vcl::Window *pWindow )
769 ImplSVData* pSVData = ImplGetSVData();
770 assert (pSVData->maFrameData.mpFirstFrame.get() != pWindow);
771 mpNextFrame = pSVData->maFrameData.mpFirstFrame;
772 pSVData->maFrameData.mpFirstFrame = pWindow;
773 mpFirstOverlap = nullptr;
774 mpFocusWin = nullptr;
775 mpMouseMoveWin = nullptr;
776 mpMouseDownWin = nullptr;
777 mxFontCollection = pSVData->maGDIData.mxScreenFontList;
778 mxFontCache = pSVData->maGDIData.mxScreenFontCache;
779 mnFocusId = nullptr;
780 mnMouseMoveId = nullptr;
781 mnLastMouseX = -1;
782 mnLastMouseY = -1;
783 mnBeforeLastMouseX = -1;
784 mnBeforeLastMouseY = -1;
785 mnFirstMouseX = -1;
786 mnFirstMouseY = -1;
787 mnLastMouseWinX = -1;
788 mnLastMouseWinY = -1;
789 mnModalMode = 0;
790 mnMouseDownTime = 0;
791 mnClickCount = 0;
792 mnFirstMouseCode = 0;
793 mnMouseCode = 0;
794 mnMouseMode = MouseEventModifiers::NONE;
795 mbHasFocus = false;
796 mbInMouseMove = false;
797 mbMouseIn = false;
798 mbStartDragCalled = false;
799 mbNeedSysWindow = false;
800 mbMinimized = false;
801 mbStartFocusState = false;
802 mbInSysObjFocusHdl = false;
803 mbInSysObjToTopHdl = false;
804 mbSysObjFocus = false;
805 maPaintIdle.SetPriority( TaskPriority::REPAINT );
806 maPaintIdle.SetInvokeHandler( LINK( pWindow, vcl::Window, ImplHandlePaintHdl ) );
807 maPaintIdle.SetDebugName( "vcl::Window maPaintIdle" );
808 maResizeIdle.SetPriority( TaskPriority::RESIZE );
809 maResizeIdle.SetInvokeHandler( LINK( pWindow, vcl::Window, ImplHandleResizeTimerHdl ) );
810 maResizeIdle.SetDebugName( "vcl::Window maResizeIdle" );
811 mbInternalDragGestureRecognizer = false;
812 mbInBufferedPaint = false;
813 mnDPIX = 96;
814 mnDPIY = 96;
815 mnTouchPanPosition = -1;
818 namespace vcl {
820 bool Window::AcquireGraphics() const
822 DBG_TESTSOLARMUTEX();
824 if ( mpGraphics )
825 return true;
827 mbInitLineColor = true;
828 mbInitFillColor = true;
829 mbInitFont = true;
830 mbInitTextColor = true;
831 mbInitClipRegion = true;
833 ImplSVData* pSVData = ImplGetSVData();
835 mpGraphics = mpWindowImpl->mpFrame->AcquireGraphics();
836 // try harder if no wingraphics was available directly
837 if ( !mpGraphics )
839 // find another output device in the same frame
840 OutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics;
841 while ( pReleaseOutDev )
843 if ( static_cast<vcl::Window*>(pReleaseOutDev)->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame )
844 break;
845 pReleaseOutDev = pReleaseOutDev->mpPrevGraphics;
848 if ( pReleaseOutDev )
850 // steal the wingraphics from the other outdev
851 mpGraphics = pReleaseOutDev->mpGraphics;
852 pReleaseOutDev->ReleaseGraphics( false );
854 else
856 // if needed retry after releasing least recently used wingraphics
857 while ( !mpGraphics )
859 if ( !pSVData->maGDIData.mpLastWinGraphics )
860 break;
861 pSVData->maGDIData.mpLastWinGraphics->ReleaseGraphics();
862 mpGraphics = mpWindowImpl->mpFrame->AcquireGraphics();
867 if ( mpGraphics )
869 // update global LRU list of wingraphics
870 mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics;
871 pSVData->maGDIData.mpFirstWinGraphics = const_cast<vcl::Window*>(this);
872 if ( mpNextGraphics )
873 mpNextGraphics->mpPrevGraphics = const_cast<vcl::Window*>(this);
874 if ( !pSVData->maGDIData.mpLastWinGraphics )
875 pSVData->maGDIData.mpLastWinGraphics = const_cast<vcl::Window*>(this);
877 mpGraphics->SetXORMode( (RasterOp::Invert == meRasterOp) || (RasterOp::Xor == meRasterOp), RasterOp::Invert == meRasterOp );
878 mpGraphics->setAntiAlias(bool(mnAntialiasing & AntialiasingFlags::Enable));
881 return mpGraphics != nullptr;
884 void Window::ReleaseGraphics( bool bRelease )
886 DBG_TESTSOLARMUTEX();
888 if ( !mpGraphics )
889 return;
891 // release the fonts of the physically released graphics device
892 if( bRelease )
893 ImplReleaseFonts();
895 ImplSVData* pSVData = ImplGetSVData();
897 vcl::Window* pWindow = this;
899 if ( bRelease )
900 pWindow->mpWindowImpl->mpFrame->ReleaseGraphics( mpGraphics );
901 // remove from global LRU list of window graphics
902 if ( mpPrevGraphics )
903 mpPrevGraphics->mpNextGraphics = mpNextGraphics;
904 else
905 pSVData->maGDIData.mpFirstWinGraphics = mpNextGraphics;
906 if ( mpNextGraphics )
907 mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
908 else
909 pSVData->maGDIData.mpLastWinGraphics = mpPrevGraphics;
911 mpGraphics = nullptr;
912 mpPrevGraphics = nullptr;
913 mpNextGraphics = nullptr;
916 static sal_Int32 CountDPIScaleFactor(sal_Int32 nDPI)
918 #ifndef MACOSX
919 // Setting of HiDPI is unfortunately all only a heuristic; and to add
920 // insult to an injury, the system is constantly lying to us about
921 // the DPI and whatnot
922 // eg. fdo#77059 - set the value from which we do consider the
923 // screen HiDPI to greater than 168
924 if (nDPI > 216) // 96 * 2 + 96 / 4
925 return 250;
926 else if (nDPI > 168) // 96 * 2 - 96 / 4
927 return 200;
928 else if (nDPI > 120) // 96 * 1.5 - 96 / 4
929 return 150;
930 #else
931 (void)nDPI;
932 #endif
934 return 100;
937 void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
939 SAL_WARN_IF( !mpWindowImpl->mbFrame && !pParent && GetType() != WindowType::FIXEDIMAGE, "vcl.window",
940 "Window::Window(): pParent == NULL" );
942 ImplSVData* pSVData = ImplGetSVData();
943 vcl::Window* pRealParent = pParent;
945 // inherit 3D look
946 if ( !mpWindowImpl->mbOverlapWin && pParent && (pParent->GetStyle() & WB_3DLOOK) )
947 nStyle |= WB_3DLOOK;
949 // create border window if necessary
950 if ( !mpWindowImpl->mbFrame && !mpWindowImpl->mbBorderWin && !mpWindowImpl->mpBorderWindow
951 && (nStyle & (WB_BORDER | WB_SYSTEMCHILDWINDOW) ) )
953 BorderWindowStyle nBorderTypeStyle = BorderWindowStyle::NONE;
954 if( nStyle & WB_SYSTEMCHILDWINDOW )
956 // handle WB_SYSTEMCHILDWINDOW
957 // these should be analogous to a top level frame; meaning they
958 // should have a border window with style BorderWindowStyle::Frame
959 // which controls their size
960 nBorderTypeStyle |= BorderWindowStyle::Frame;
961 nStyle |= WB_BORDER;
963 VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL), nBorderTypeStyle );
964 static_cast<vcl::Window*>(pBorderWin)->mpWindowImpl->mpClientWindow = this;
965 pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
966 mpWindowImpl->mpBorderWindow = pBorderWin;
967 pParent = mpWindowImpl->mpBorderWindow;
969 else if( !mpWindowImpl->mbFrame && ! pParent )
971 mpWindowImpl->mbOverlapWin = true;
972 mpWindowImpl->mbFrame = true;
975 // insert window in list
976 ImplInsertWindow( pParent );
977 mpWindowImpl->mnStyle = nStyle;
979 if( pParent && ! mpWindowImpl->mbFrame )
980 mbEnableRTL = AllSettings::GetLayoutRTL();
982 // test for frame creation
983 if ( mpWindowImpl->mbFrame )
985 // create frame
986 SalFrameStyleFlags nFrameStyle = SalFrameStyleFlags::NONE;
988 if ( nStyle & WB_MOVEABLE )
989 nFrameStyle |= SalFrameStyleFlags::MOVEABLE;
990 if ( nStyle & WB_SIZEABLE )
991 nFrameStyle |= SalFrameStyleFlags::SIZEABLE;
992 if ( nStyle & WB_CLOSEABLE )
993 nFrameStyle |= SalFrameStyleFlags::CLOSEABLE;
994 if ( nStyle & WB_APP )
995 nFrameStyle |= SalFrameStyleFlags::DEFAULT;
996 // check for undecorated floating window
997 if( // 1. floating windows that are not moveable/sizeable (only closeable allowed)
998 ( !(nFrameStyle & ~SalFrameStyleFlags::CLOSEABLE) &&
999 ( mpWindowImpl->mbFloatWin || ((GetType() == WindowType::BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow) || (nStyle & WB_SYSTEMFLOATWIN) ) ) ||
1000 // 2. borderwindows of floaters with ownerdraw decoration
1001 ((GetType() == WindowType::BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow && (nStyle & WB_OWNERDRAWDECORATION) ) )
1003 nFrameStyle = SalFrameStyleFlags::FLOAT;
1004 if( nStyle & WB_OWNERDRAWDECORATION )
1005 nFrameStyle |= SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::NOSHADOW;
1007 else if( mpWindowImpl->mbFloatWin )
1008 nFrameStyle |= SalFrameStyleFlags::TOOLWINDOW;
1010 if( nStyle & WB_INTROWIN )
1011 nFrameStyle |= SalFrameStyleFlags::INTRO;
1012 if( nStyle & WB_TOOLTIPWIN )
1013 nFrameStyle |= SalFrameStyleFlags::TOOLTIP;
1015 if( nStyle & WB_NOSHADOW )
1016 nFrameStyle |= SalFrameStyleFlags::NOSHADOW;
1018 if( nStyle & WB_SYSTEMCHILDWINDOW )
1019 nFrameStyle |= SalFrameStyleFlags::SYSTEMCHILD;
1021 switch (mpWindowImpl->mnType)
1023 case WindowType::DIALOG:
1024 case WindowType::TABDIALOG:
1025 case WindowType::MODELESSDIALOG:
1026 case WindowType::MESSBOX:
1027 case WindowType::INFOBOX:
1028 case WindowType::WARNINGBOX:
1029 case WindowType::ERRORBOX:
1030 case WindowType::QUERYBOX:
1031 nFrameStyle |= SalFrameStyleFlags::DIALOG;
1032 break;
1033 default:
1034 break;
1037 SalFrame* pParentFrame = nullptr;
1038 if ( pParent )
1039 pParentFrame = pParent->mpWindowImpl->mpFrame;
1040 SalFrame* pFrame;
1041 if ( pSystemParentData )
1042 pFrame = pSVData->mpDefInst->CreateChildFrame( pSystemParentData, nFrameStyle | SalFrameStyleFlags::PLUG );
1043 else
1044 pFrame = pSVData->mpDefInst->CreateFrame( pParentFrame, nFrameStyle );
1045 if ( !pFrame )
1047 // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
1048 throw RuntimeException(
1049 "Could not create system window!",
1050 Reference< XInterface >() );
1053 pFrame->SetCallback( this, ImplWindowFrameProc );
1055 // set window frame data
1056 mpWindowImpl->mpFrameData = new ImplFrameData( this );
1057 mpWindowImpl->mpFrame = pFrame;
1058 mpWindowImpl->mpFrameWindow = this;
1059 mpWindowImpl->mpOverlapWindow = this;
1061 if (!(nStyle & WB_DEFAULTWIN) && mpWindowImpl->mbDoubleBufferingRequested)
1062 RequestDoubleBuffering(true);
1064 if ( pRealParent && IsTopWindow() )
1066 ImplWinData* pParentWinData = pRealParent->ImplGetWinData();
1067 pParentWinData->maTopWindowChildren.emplace_back(this );
1071 // init data
1072 mpWindowImpl->mpRealParent = pRealParent;
1074 // #99318: make sure fontcache and list is available before call to SetSettings
1075 mxFontCollection = mpWindowImpl->mpFrameData->mxFontCollection;
1076 mxFontCache = mpWindowImpl->mpFrameData->mxFontCache;
1078 if ( mpWindowImpl->mbFrame )
1080 if ( pParent )
1082 mpWindowImpl->mpFrameData->mnDPIX = pParent->mpWindowImpl->mpFrameData->mnDPIX;
1083 mpWindowImpl->mpFrameData->mnDPIY = pParent->mpWindowImpl->mpFrameData->mnDPIY;
1085 else
1087 OutputDevice *pOutDev = GetOutDev();
1088 if ( pOutDev->AcquireGraphics() )
1090 mpGraphics->GetResolution( mpWindowImpl->mpFrameData->mnDPIX, mpWindowImpl->mpFrameData->mnDPIY );
1094 // add ownerdraw decorated frame windows to list in the top-most frame window
1095 // so they can be hidden on lose focus
1096 if( nStyle & WB_OWNERDRAWDECORATION )
1097 ImplGetOwnerDrawList().emplace_back(this );
1099 // delay settings initialization until first "real" frame
1100 // this relies on the IntroWindow not needing any system settings
1101 if ( !pSVData->maAppData.mbSettingsInit &&
1102 ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN))
1105 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
1106 ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings );
1107 OutputDevice::SetSettings( *pSVData->maAppData.mpSettings );
1108 pSVData->maAppData.mbSettingsInit = true;
1111 // If we create a Window with default size, query this
1112 // size directly, because we want resize all Controls to
1113 // the correct size before we display the window
1114 if ( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_APP) )
1115 mpWindowImpl->mpFrame->GetClientSize( mnOutWidth, mnOutHeight );
1117 else
1119 if ( pParent )
1121 if ( !ImplIsOverlapWindow() )
1123 mpWindowImpl->mbDisabled = pParent->mpWindowImpl->mbDisabled;
1124 mpWindowImpl->mbInputDisabled = pParent->mpWindowImpl->mbInputDisabled;
1125 mpWindowImpl->meAlwaysInputMode = pParent->mpWindowImpl->meAlwaysInputMode;
1128 if (!utl::ConfigManager::IsFuzzing())
1129 OutputDevice::SetSettings( pParent->GetSettings() );
1134 // setup the scale factor for HiDPI displays
1135 mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
1136 mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
1137 mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
1139 if (!utl::ConfigManager::IsFuzzing())
1141 const StyleSettings& rStyleSettings = mxSettings->GetStyleSettings();
1142 maFont = rStyleSettings.GetAppFont();
1144 if ( nStyle & WB_3DLOOK )
1146 SetTextColor( rStyleSettings.GetButtonTextColor() );
1147 SetBackground( Wallpaper( rStyleSettings.GetFaceColor() ) );
1149 else
1151 SetTextColor( rStyleSettings.GetWindowTextColor() );
1152 SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
1155 else
1157 maFont = GetDefaultFont( DefaultFontType::FIXED, LANGUAGE_ENGLISH_US, GetDefaultFontFlags::NONE );
1160 ImplPointToLogic(*this, maFont);
1162 (void)ImplUpdatePos();
1164 // calculate app font res (except for the Intro Window or the default window)
1165 if ( mpWindowImpl->mbFrame && !pSVData->maGDIData.mnAppFontX && ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN)) )
1166 ImplInitAppFontData( this );
1169 void Window::ImplInitAppFontData( vcl::Window const * pWindow )
1171 ImplSVData* pSVData = ImplGetSVData();
1172 tools::Long nTextHeight = pWindow->GetTextHeight();
1173 tools::Long nTextWidth = pWindow->approximate_char_width() * 8;
1174 tools::Long nSymHeight = nTextHeight*4;
1175 // Make the basis wider if the font is too narrow
1176 // such that the dialog looks symmetrical and does not become too narrow.
1177 // Add some extra space when the dialog has the same width,
1178 // as a little more space is better.
1179 if ( nSymHeight > nTextWidth )
1180 nTextWidth = nSymHeight;
1181 else if ( nSymHeight+5 > nTextWidth )
1182 nTextWidth = nSymHeight+5;
1183 pSVData->maGDIData.mnAppFontX = nTextWidth * 10 / 8;
1184 pSVData->maGDIData.mnAppFontY = nTextHeight * 10;
1186 #ifdef MACOSX
1187 // FIXME: this is currently only on macOS, check with other
1188 // platforms
1189 if( pSVData->maNWFData.mbNoFocusRects )
1191 // try to find out whether there is a large correction
1192 // of control sizes, if yes, make app font scalings larger
1193 // so dialog positioning is not completely off
1194 ImplControlValue aControlValue;
1195 tools::Rectangle aCtrlRegion( Point(), Size( nTextWidth < 10 ? 10 : nTextWidth, nTextHeight < 10 ? 10 : nTextHeight ) );
1196 tools::Rectangle aBoundingRgn( aCtrlRegion );
1197 tools::Rectangle aContentRgn( aCtrlRegion );
1198 if( pWindow->GetNativeControlRegion( ControlType::Editbox, ControlPart::Entire, aCtrlRegion,
1199 ControlState::ENABLED, aControlValue,
1200 aBoundingRgn, aContentRgn ) )
1202 // comment: the magical +6 is for the extra border in bordered
1203 // (which is the standard) edit fields
1204 if( aContentRgn.GetHeight() - nTextHeight > (nTextHeight+4)/4 )
1205 pSVData->maGDIData.mnAppFontY = (aContentRgn.GetHeight()-4) * 10;
1208 #endif
1211 ImplWinData* Window::ImplGetWinData() const
1213 if (!mpWindowImpl->mpWinData)
1215 static const char* pNoNWF = getenv( "SAL_NO_NWF" );
1217 const_cast<vcl::Window*>(this)->mpWindowImpl->mpWinData = new ImplWinData;
1218 mpWindowImpl->mpWinData->mbEnableNativeWidget = !(pNoNWF && *pNoNWF); // true: try to draw this control with native theme API
1221 return mpWindowImpl->mpWinData;
1225 void Window::CopyDeviceArea( SalTwoRect& aPosAry, bool bWindowInvalidate )
1227 if (aPosAry.mnSrcWidth == 0 || aPosAry.mnSrcHeight == 0 || aPosAry.mnDestWidth == 0 || aPosAry.mnDestHeight == 0)
1228 return;
1230 if (bWindowInvalidate)
1232 const tools::Rectangle aSrcRect(Point(aPosAry.mnSrcX, aPosAry.mnSrcY),
1233 Size(aPosAry.mnSrcWidth, aPosAry.mnSrcHeight));
1235 ImplMoveAllInvalidateRegions(aSrcRect,
1236 aPosAry.mnDestX-aPosAry.mnSrcX,
1237 aPosAry.mnDestY-aPosAry.mnSrcY,
1238 false);
1240 mpGraphics->CopyArea(aPosAry.mnDestX, aPosAry.mnDestY,
1241 aPosAry.mnSrcX, aPosAry.mnSrcY,
1242 aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
1243 this);
1245 return;
1248 OutputDevice::CopyDeviceArea(aPosAry, bWindowInvalidate);
1251 const OutputDevice* Window::DrawOutDevDirectCheck(const OutputDevice* pSrcDev) const
1253 const OutputDevice* pSrcDevChecked;
1254 if ( this == pSrcDev )
1255 pSrcDevChecked = nullptr;
1256 else if (GetOutDevType() != pSrcDev->GetOutDevType())
1257 pSrcDevChecked = pSrcDev;
1258 else if (this->mpWindowImpl->mpFrameWindow == static_cast<const vcl::Window*>(pSrcDev)->mpWindowImpl->mpFrameWindow)
1259 pSrcDevChecked = nullptr;
1260 else
1261 pSrcDevChecked = pSrcDev;
1263 return pSrcDevChecked;
1266 void Window::DrawOutDevDirectProcess( const OutputDevice* pSrcDev, SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
1268 mpGraphics->CopyBits( rPosAry, pSrcGraphics, this, pSrcDev );
1271 SalGraphics* Window::ImplGetFrameGraphics() const
1273 if ( mpWindowImpl->mpFrameWindow->mpGraphics )
1275 mpWindowImpl->mpFrameWindow->mbInitClipRegion = true;
1277 else
1279 OutputDevice* pFrameWinOutDev = mpWindowImpl->mpFrameWindow;
1280 if ( ! pFrameWinOutDev->AcquireGraphics() )
1282 return nullptr;
1285 mpWindowImpl->mpFrameWindow->mpGraphics->ResetClipRegion();
1286 return mpWindowImpl->mpFrameWindow->mpGraphics;
1289 void Window::ImplSetReallyVisible()
1291 // #i43594# it is possible that INITSHOW was never send, because the visibility state changed between
1292 // ImplCallInitShow() and ImplSetReallyVisible() when called from Show()
1293 // mbReallyShown is a useful indicator
1294 if( !mpWindowImpl->mbReallyShown )
1295 ImplCallInitShow();
1297 bool bBecameReallyVisible = !mpWindowImpl->mbReallyVisible;
1299 mbDevOutput = true;
1300 mpWindowImpl->mbReallyVisible = true;
1301 mpWindowImpl->mbReallyShown = true;
1303 // the SHOW/HIDE events serve as indicators to send child creation/destroy events to the access bridge.
1304 // For this, the data member of the event must not be NULL.
1305 // Previously, we did this in Window::Show, but there some events got lost in certain situations. Now
1306 // we're doing it when the visibility really changes
1307 if( bBecameReallyVisible && ImplIsAccessibleCandidate() )
1308 CallEventListeners( VclEventId::WindowShow, this );
1309 // TODO. It's kind of a hack that we're re-using the VclEventId::WindowShow. Normally, we should
1310 // introduce another event which explicitly triggers the Accessibility implementations.
1312 vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
1313 while ( pWindow )
1315 if ( pWindow->mpWindowImpl->mbVisible )
1316 pWindow->ImplSetReallyVisible();
1317 pWindow = pWindow->mpWindowImpl->mpNext;
1320 pWindow = mpWindowImpl->mpFirstChild;
1321 while ( pWindow )
1323 if ( pWindow->mpWindowImpl->mbVisible )
1324 pWindow->ImplSetReallyVisible();
1325 pWindow = pWindow->mpWindowImpl->mpNext;
1329 void Window::ImplInitResolutionSettings()
1331 // recalculate AppFont-resolution and DPI-resolution
1332 if (mpWindowImpl->mbFrame)
1334 mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
1335 mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
1337 // setup the scale factor for HiDPI displays
1338 mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
1339 const StyleSettings& rStyleSettings = mxSettings->GetStyleSettings();
1340 SetPointFont(*this, rStyleSettings.GetAppFont());
1342 else if ( mpWindowImpl->mpParent )
1344 mnDPIX = mpWindowImpl->mpParent->mnDPIX;
1345 mnDPIY = mpWindowImpl->mpParent->mnDPIY;
1346 mnDPIScalePercentage = mpWindowImpl->mpParent->mnDPIScalePercentage;
1349 // update the recalculated values for logical units
1350 // and also tools belonging to the values
1351 if (IsMapModeEnabled())
1353 MapMode aMapMode = GetMapMode();
1354 SetMapMode();
1355 SetMapMode( aMapMode );
1359 void Window::ImplPointToLogic(vcl::RenderContext const & rRenderContext, vcl::Font& rFont) const
1361 Size aSize = rFont.GetFontSize();
1363 if (aSize.Width())
1365 aSize.setWidth( aSize.Width() * ( mpWindowImpl->mpFrameData->mnDPIX) );
1366 aSize.AdjustWidth(72 / 2 );
1367 aSize.setWidth( aSize.Width() / 72 );
1369 aSize.setHeight( aSize.Height() * ( mpWindowImpl->mpFrameData->mnDPIY) );
1370 aSize.AdjustHeight(72/2 );
1371 aSize.setHeight( aSize.Height() / 72 );
1373 if (rRenderContext.IsMapModeEnabled())
1374 aSize = rRenderContext.PixelToLogic(aSize);
1376 rFont.SetFontSize(aSize);
1379 void Window::ImplLogicToPoint(vcl::RenderContext const & rRenderContext, vcl::Font& rFont) const
1381 Size aSize = rFont.GetFontSize();
1383 if (rRenderContext.IsMapModeEnabled())
1384 aSize = rRenderContext.LogicToPixel(aSize);
1386 if (aSize.Width())
1388 aSize.setWidth( aSize.Width() * 72 );
1389 aSize.AdjustWidth(mpWindowImpl->mpFrameData->mnDPIX / 2 );
1390 aSize.setWidth( aSize.Width() / ( mpWindowImpl->mpFrameData->mnDPIX) );
1392 aSize.setHeight( aSize.Height() * 72 );
1393 aSize.AdjustHeight(mpWindowImpl->mpFrameData->mnDPIY / 2 );
1394 aSize.setHeight( aSize.Height() / ( mpWindowImpl->mpFrameData->mnDPIY) );
1396 rFont.SetFontSize(aSize);
1399 bool Window::ImplUpdatePos()
1401 bool bSysChild = false;
1403 if ( ImplIsOverlapWindow() )
1405 mnOutOffX = mpWindowImpl->mnX;
1406 mnOutOffY = mpWindowImpl->mnY;
1408 else
1410 vcl::Window* pParent = ImplGetParent();
1412 mnOutOffX = mpWindowImpl->mnX + pParent->mnOutOffX;
1413 mnOutOffY = mpWindowImpl->mnY + pParent->mnOutOffY;
1416 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
1417 while ( pChild )
1419 if ( pChild->ImplUpdatePos() )
1420 bSysChild = true;
1421 pChild = pChild->mpWindowImpl->mpNext;
1424 if ( mpWindowImpl->mpSysObj )
1425 bSysChild = true;
1427 return bSysChild;
1430 void Window::ImplUpdateSysObjPos()
1432 if ( mpWindowImpl->mpSysObj )
1433 mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
1435 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
1436 while ( pChild )
1438 pChild->ImplUpdateSysObjPos();
1439 pChild = pChild->mpWindowImpl->mpNext;
1443 void Window::ImplPosSizeWindow( tools::Long nX, tools::Long nY,
1444 tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags )
1446 bool bNewPos = false;
1447 bool bNewSize = false;
1448 bool bCopyBits = false;
1449 tools::Long nOldOutOffX = mnOutOffX;
1450 tools::Long nOldOutOffY = mnOutOffY;
1451 tools::Long nOldOutWidth = mnOutWidth;
1452 tools::Long nOldOutHeight = mnOutHeight;
1453 std::unique_ptr<vcl::Region> pOverlapRegion;
1454 std::unique_ptr<vcl::Region> pOldRegion;
1456 if ( IsReallyVisible() )
1458 tools::Rectangle aOldWinRect( Point( nOldOutOffX, nOldOutOffY ),
1459 Size( nOldOutWidth, nOldOutHeight ) );
1460 pOldRegion.reset( new vcl::Region( aOldWinRect ) );
1461 if ( mpWindowImpl->mbWinRegion )
1462 pOldRegion->Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1464 if ( mnOutWidth && mnOutHeight && !mpWindowImpl->mbPaintTransparent &&
1465 !mpWindowImpl->mbInitWinClipRegion && !mpWindowImpl->maWinClipRegion.IsEmpty() &&
1466 !HasPaintEvent() )
1467 bCopyBits = true;
1470 bool bnXRecycled = false; // avoid duplicate mirroring in RTL case
1471 if ( nFlags & PosSizeFlags::Width )
1473 if(!( nFlags & PosSizeFlags::X ))
1475 nX = mpWindowImpl->mnX;
1476 nFlags |= PosSizeFlags::X;
1477 bnXRecycled = true; // we're using a mnX which was already mirrored in RTL case
1480 if ( nWidth < 0 )
1481 nWidth = 0;
1482 if ( nWidth != mnOutWidth )
1484 mnOutWidth = nWidth;
1485 bNewSize = true;
1486 bCopyBits = false;
1489 if ( nFlags & PosSizeFlags::Height )
1491 if ( nHeight < 0 )
1492 nHeight = 0;
1493 if ( nHeight != mnOutHeight )
1495 mnOutHeight = nHeight;
1496 bNewSize = true;
1497 bCopyBits = false;
1501 if ( nFlags & PosSizeFlags::X )
1503 tools::Long nOrgX = nX;
1504 Point aPtDev( Point( nX+mnOutOffX, 0 ) );
1505 OutputDevice *pOutDev = GetOutDev();
1506 if( pOutDev->HasMirroredGraphics() )
1508 aPtDev.setX( mpGraphics->mirror2( aPtDev.X(), this ) );
1510 // #106948# always mirror our pos if our parent is not mirroring, even
1511 // if we are also not mirroring
1512 // RTL: check if parent is in different coordinates
1513 if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
1515 nX = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - nX;
1517 /* #i99166# An LTR window in RTL UI that gets sized only would be
1518 expected to not moved its upper left point
1520 if( bnXRecycled )
1522 if( ImplIsAntiparallel() )
1524 aPtDev.setX( mpWindowImpl->mnAbsScreenX );
1525 nOrgX = mpWindowImpl->maPos.X();
1529 else if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
1531 // mirrored window in LTR UI
1532 nX = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - nX;
1535 // check maPos as well, as it could have been changed for client windows (ImplCallMove())
1536 if ( mpWindowImpl->mnAbsScreenX != aPtDev.X() || nX != mpWindowImpl->mnX || nOrgX != mpWindowImpl->maPos.X() )
1538 if ( bCopyBits && !pOverlapRegion )
1540 pOverlapRegion.reset( new vcl::Region() );
1541 ImplCalcOverlapRegion( tools::Rectangle( Point( mnOutOffX, mnOutOffY ),
1542 Size( mnOutWidth, mnOutHeight ) ),
1543 *pOverlapRegion, false, true );
1545 mpWindowImpl->mnX = nX;
1546 mpWindowImpl->maPos.setX( nOrgX );
1547 mpWindowImpl->mnAbsScreenX = aPtDev.X();
1548 bNewPos = true;
1551 if ( nFlags & PosSizeFlags::Y )
1553 // check maPos as well, as it could have been changed for client windows (ImplCallMove())
1554 if ( nY != mpWindowImpl->mnY || nY != mpWindowImpl->maPos.Y() )
1556 if ( bCopyBits && !pOverlapRegion )
1558 pOverlapRegion.reset( new vcl::Region() );
1559 ImplCalcOverlapRegion( tools::Rectangle( Point( mnOutOffX, mnOutOffY ),
1560 Size( mnOutWidth, mnOutHeight ) ),
1561 *pOverlapRegion, false, true );
1563 mpWindowImpl->mnY = nY;
1564 mpWindowImpl->maPos.setY( nY );
1565 bNewPos = true;
1569 if ( !(bNewPos || bNewSize) )
1570 return;
1572 bool bUpdateSysObjPos = false;
1573 if ( bNewPos )
1574 bUpdateSysObjPos = ImplUpdatePos();
1576 // the borderwindow always specifies the position for its client window
1577 if ( mpWindowImpl->mpBorderWindow )
1578 mpWindowImpl->maPos = mpWindowImpl->mpBorderWindow->mpWindowImpl->maPos;
1580 if ( mpWindowImpl->mpClientWindow )
1582 mpWindowImpl->mpClientWindow->ImplPosSizeWindow( mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder,
1583 mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder,
1584 mnOutWidth-mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnRightBorder,
1585 mnOutHeight-mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnBottomBorder,
1586 PosSizeFlags::X | PosSizeFlags::Y |
1587 PosSizeFlags::Width | PosSizeFlags::Height );
1588 // If we have a client window, then this is the position
1589 // of the Application's floating windows
1590 mpWindowImpl->mpClientWindow->mpWindowImpl->maPos = mpWindowImpl->maPos;
1591 if ( bNewPos )
1593 if ( mpWindowImpl->mpClientWindow->IsVisible() )
1595 mpWindowImpl->mpClientWindow->ImplCallMove();
1597 else
1599 mpWindowImpl->mpClientWindow->mpWindowImpl->mbCallMove = true;
1604 // Move()/Resize() will be called only for Show(), such that
1605 // at least one is called before Show()
1606 if ( IsVisible() )
1608 if ( bNewPos )
1610 ImplCallMove();
1612 if ( bNewSize )
1614 ImplCallResize();
1617 else
1619 if ( bNewPos )
1620 mpWindowImpl->mbCallMove = true;
1621 if ( bNewSize )
1622 mpWindowImpl->mbCallResize = true;
1625 bool bUpdateSysObjClip = false;
1626 if ( IsReallyVisible() )
1628 if ( bNewPos || bNewSize )
1630 // set Clip-Flag
1631 bUpdateSysObjClip = !ImplSetClipFlag( true );
1634 // invalidate window content ?
1635 if ( bNewPos || (mnOutWidth > nOldOutWidth) || (mnOutHeight > nOldOutHeight) )
1637 if ( bNewPos )
1639 bool bInvalidate = false;
1640 bool bParentPaint = true;
1641 if ( !ImplIsOverlapWindow() )
1642 bParentPaint = mpWindowImpl->mpParent->IsPaintEnabled();
1643 if ( bCopyBits && bParentPaint && !HasPaintEvent() )
1645 Point aPoint( mnOutOffX, mnOutOffY );
1646 vcl::Region aRegion( tools::Rectangle( aPoint,
1647 Size( mnOutWidth, mnOutHeight ) ) );
1648 if ( mpWindowImpl->mbWinRegion )
1649 aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1650 ImplClipBoundaries( aRegion, false, true );
1651 if ( !pOverlapRegion->IsEmpty() )
1653 pOverlapRegion->Move( mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY );
1654 aRegion.Exclude( *pOverlapRegion );
1656 if ( !aRegion.IsEmpty() )
1658 // adapt Paint areas
1659 ImplMoveAllInvalidateRegions( tools::Rectangle( Point( nOldOutOffX, nOldOutOffY ),
1660 Size( nOldOutWidth, nOldOutHeight ) ),
1661 mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY,
1662 true );
1663 SalGraphics* pGraphics = ImplGetFrameGraphics();
1664 if ( pGraphics )
1667 OutputDevice *pOutDev = GetOutDev();
1668 const bool bSelectClipRegion = pOutDev->SelectClipRegion( aRegion, pGraphics );
1669 if ( bSelectClipRegion )
1671 pGraphics->CopyArea( mnOutOffX, mnOutOffY,
1672 nOldOutOffX, nOldOutOffY,
1673 nOldOutWidth, nOldOutHeight,
1674 this );
1676 else
1677 bInvalidate = true;
1679 else
1680 bInvalidate = true;
1681 if ( !bInvalidate )
1683 if ( !pOverlapRegion->IsEmpty() )
1684 ImplInvalidateFrameRegion( pOverlapRegion.get(), InvalidateFlags::Children );
1687 else
1688 bInvalidate = true;
1690 else
1691 bInvalidate = true;
1692 if ( bInvalidate )
1693 ImplInvalidateFrameRegion( nullptr, InvalidateFlags::Children );
1695 else
1697 Point aPoint( mnOutOffX, mnOutOffY );
1698 vcl::Region aRegion( tools::Rectangle( aPoint,
1699 Size( mnOutWidth, mnOutHeight ) ) );
1700 aRegion.Exclude( *pOldRegion );
1701 if ( mpWindowImpl->mbWinRegion )
1702 aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1703 ImplClipBoundaries( aRegion, false, true );
1704 if ( !aRegion.IsEmpty() )
1705 ImplInvalidateFrameRegion( &aRegion, InvalidateFlags::Children );
1709 // invalidate Parent or Overlaps
1710 if ( bNewPos ||
1711 (mnOutWidth < nOldOutWidth) || (mnOutHeight < nOldOutHeight) )
1713 vcl::Region aRegion( *pOldRegion );
1714 if ( !mpWindowImpl->mbPaintTransparent )
1715 ImplExcludeWindowRegion( aRegion );
1716 ImplClipBoundaries( aRegion, false, true );
1717 if ( !aRegion.IsEmpty() && !mpWindowImpl->mpBorderWindow )
1718 ImplInvalidateParentFrameRegion( aRegion );
1722 // adapt system objects
1723 if ( bUpdateSysObjClip )
1724 ImplUpdateSysObjClip();
1725 if ( bUpdateSysObjPos )
1726 ImplUpdateSysObjPos();
1727 if ( bNewSize && mpWindowImpl->mpSysObj )
1728 mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
1731 void Window::ImplNewInputContext()
1733 ImplSVData* pSVData = ImplGetSVData();
1734 vcl::Window* pFocusWin = pSVData->mpWinData->mpFocusWin;
1735 if ( !pFocusWin || pFocusWin->IsDisposed() )
1736 return;
1738 // Is InputContext changed?
1739 const InputContext& rInputContext = pFocusWin->GetInputContext();
1740 if ( rInputContext == pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext )
1741 return;
1743 pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext = rInputContext;
1745 SalInputContext aNewContext;
1746 const vcl::Font& rFont = rInputContext.GetFont();
1747 const OUString& rFontName = rFont.GetFamilyName();
1748 rtl::Reference<LogicalFontInstance> pFontInstance;
1749 aNewContext.mpFont = nullptr;
1750 if (!rFontName.isEmpty())
1752 OutputDevice *pFocusWinOutDev = pFocusWin->GetOutDev();
1753 Size aSize = pFocusWinOutDev->ImplLogicToDevicePixel( rFont.GetFontSize() );
1754 if ( !aSize.Height() )
1756 // only set default sizes if the font height in logical
1757 // coordinates equals 0
1758 if ( rFont.GetFontSize().Height() )
1759 aSize.setHeight( 1 );
1760 else
1761 aSize.setHeight( (12*pFocusWin->mnDPIY)/72 );
1763 pFontInstance = pFocusWin->mxFontCache->GetFontInstance( pFocusWin->mxFontCollection.get(),
1764 rFont, aSize, static_cast<float>(aSize.Height()) );
1765 if ( pFontInstance )
1766 aNewContext.mpFont = pFontInstance;
1768 aNewContext.mnOptions = rInputContext.GetOptions();
1769 pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
1772 void Window::SetDumpAsPropertyTreeHdl(const Link<tools::JsonWriter&, void>& rLink)
1774 if (mpWindowImpl) // may be called after dispose
1776 mpWindowImpl->maDumpAsPropertyTreeHdl = rLink;
1780 void Window::SetModalHierarchyHdl(const Link<bool, void>& rLink)
1782 ImplGetFrame()->SetModalHierarchyHdl(rLink);
1785 void Window::SetParentToDefaultWindow()
1787 Show(false);
1788 SetParent(ImplGetDefaultWindow());
1791 KeyIndicatorState Window::GetIndicatorState() const
1793 return mpWindowImpl->mpFrame->GetIndicatorState();
1796 void Window::SimulateKeyPress( sal_uInt16 nKeyCode ) const
1798 mpWindowImpl->mpFrame->SimulateKeyPress(nKeyCode);
1801 void Window::KeyInput( const KeyEvent& rKEvt )
1803 KeyCode cod = rKEvt.GetKeyCode ();
1804 bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel;
1806 // do not respond to accelerators unless Alt or Ctrl is held */
1807 if (cod.GetCode () >= 0x200 && cod.GetCode () <= 0x219)
1809 if (autoacc && cod.GetModifier () != KEY_MOD2 && !(cod.GetModifier() & KEY_MOD1))
1810 return;
1813 NotifyEvent aNEvt( MouseNotifyEvent::KEYINPUT, this, &rKEvt );
1814 if ( !CompatNotify( aNEvt ) )
1815 mpWindowImpl->mbKeyInput = true;
1818 void Window::KeyUp( const KeyEvent& rKEvt )
1820 NotifyEvent aNEvt( MouseNotifyEvent::KEYUP, this, &rKEvt );
1821 if ( !CompatNotify( aNEvt ) )
1822 mpWindowImpl->mbKeyUp = true;
1825 void Window::Draw( OutputDevice*, const Point&, DrawFlags )
1829 void Window::Move() {}
1831 void Window::Resize() {}
1833 void Window::Activate() {}
1835 void Window::Deactivate() {}
1837 void Window::GetFocus()
1839 if ( HasFocus() && mpWindowImpl->mpLastFocusWindow && !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) )
1841 VclPtr<vcl::Window> xWindow(this);
1842 mpWindowImpl->mpLastFocusWindow->GrabFocus();
1843 if( xWindow->IsDisposed() )
1844 return;
1847 NotifyEvent aNEvt( MouseNotifyEvent::GETFOCUS, this );
1848 CompatNotify( aNEvt );
1851 void Window::LoseFocus()
1853 NotifyEvent aNEvt( MouseNotifyEvent::LOSEFOCUS, this );
1854 CompatNotify( aNEvt );
1857 void Window::SetHelpHdl(const Link<vcl::Window&, bool>& rLink)
1859 if (mpWindowImpl) // may be called after dispose
1861 mpWindowImpl->maHelpRequestHdl = rLink;
1865 void Window::RequestHelp( const HelpEvent& rHEvt )
1867 // if Balloon-Help is requested, show the balloon
1868 // with help text set
1869 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
1871 OUString rStr = GetHelpText();
1872 if ( rStr.isEmpty() )
1873 rStr = GetQuickHelpText();
1874 if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
1875 ImplGetParent()->RequestHelp( rHEvt );
1876 else
1878 Point aPos = GetPosPixel();
1879 if ( ImplGetParent() && !ImplIsOverlapWindow() )
1880 aPos = OutputToScreenPixel(Point(0, 0));
1881 tools::Rectangle aRect( aPos, GetSizePixel() );
1883 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aRect, rStr );
1886 else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
1888 const OUString& rStr = GetQuickHelpText();
1889 if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
1890 ImplGetParent()->RequestHelp( rHEvt );
1891 else
1893 Point aPos = GetPosPixel();
1894 if ( ImplGetParent() && !ImplIsOverlapWindow() )
1895 aPos = OutputToScreenPixel(Point(0, 0));
1896 tools::Rectangle aRect( aPos, GetSizePixel() );
1897 Help::ShowQuickHelp( this, aRect, rStr, QuickHelpFlags::CtrlText );
1900 else if (!mpWindowImpl->maHelpRequestHdl.IsSet() || mpWindowImpl->maHelpRequestHdl.Call(*this))
1902 OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
1903 if ( aStrHelpId.isEmpty() && ImplGetParent() )
1904 ImplGetParent()->RequestHelp( rHEvt );
1905 else
1907 Help* pHelp = Application::GetHelp();
1908 if ( pHelp )
1910 if( !aStrHelpId.isEmpty() )
1911 pHelp->Start( aStrHelpId, this );
1912 else
1913 pHelp->Start( OOO_HELP_INDEX, this );
1919 void Window::Command( const CommandEvent& rCEvt )
1921 CallEventListeners( VclEventId::WindowCommand, const_cast<CommandEvent *>(&rCEvt) );
1923 NotifyEvent aNEvt( MouseNotifyEvent::COMMAND, this, &rCEvt );
1924 if ( !CompatNotify( aNEvt ) )
1925 mpWindowImpl->mbCommand = true;
1928 void Window::Tracking( const TrackingEvent& rTEvt )
1931 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1932 if( pWrapper )
1933 pWrapper->Tracking( rTEvt );
1936 void Window::StateChanged(StateChangedType eType)
1938 switch (eType)
1940 //stuff that doesn't invalidate the layout
1941 case StateChangedType::ControlForeground:
1942 case StateChangedType::ControlBackground:
1943 case StateChangedType::UpdateMode:
1944 case StateChangedType::ReadOnly:
1945 case StateChangedType::Enable:
1946 case StateChangedType::State:
1947 case StateChangedType::Data:
1948 case StateChangedType::InitShow:
1949 case StateChangedType::ControlFocus:
1950 break;
1951 //stuff that does invalidate the layout
1952 default:
1953 queue_resize(eType);
1954 break;
1958 void Window::SetStyle( WinBits nStyle )
1960 if ( mpWindowImpl && mpWindowImpl->mnStyle != nStyle )
1962 mpWindowImpl->mnPrevStyle = mpWindowImpl->mnStyle;
1963 mpWindowImpl->mnStyle = nStyle;
1964 CompatStateChanged( StateChangedType::Style );
1968 void Window::SetExtendedStyle( WindowExtendedStyle nExtendedStyle )
1971 if ( mpWindowImpl->mnExtendedStyle == nExtendedStyle )
1972 return;
1974 vcl::Window* pWindow = ImplGetBorderWindow();
1975 if( ! pWindow )
1976 pWindow = this;
1977 if( pWindow->mpWindowImpl->mbFrame )
1979 SalExtStyle nExt = 0;
1980 if( nExtendedStyle & WindowExtendedStyle::Document )
1981 nExt |= SAL_FRAME_EXT_STYLE_DOCUMENT;
1982 if( nExtendedStyle & WindowExtendedStyle::DocModified )
1983 nExt |= SAL_FRAME_EXT_STYLE_DOCMODIFIED;
1985 pWindow->ImplGetFrame()->SetExtendedFrameStyle( nExt );
1987 mpWindowImpl->mnExtendedStyle = nExtendedStyle;
1990 void Window::SetBorderStyle( WindowBorderStyle nBorderStyle )
1993 if ( !mpWindowImpl->mpBorderWindow )
1994 return;
1996 if( nBorderStyle == WindowBorderStyle::REMOVEBORDER &&
1997 ! mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame &&
1998 mpWindowImpl->mpBorderWindow->mpWindowImpl->mpParent
2001 // this is a little awkward: some controls (e.g. svtools ProgressBar)
2002 // cannot avoid getting constructed with WB_BORDER but want to disable
2003 // borders in case of NWF drawing. So they need a method to remove their border window
2004 VclPtr<vcl::Window> pBorderWin = mpWindowImpl->mpBorderWindow;
2005 // remove us as border window's client
2006 pBorderWin->mpWindowImpl->mpClientWindow = nullptr;
2007 mpWindowImpl->mpBorderWindow = nullptr;
2008 mpWindowImpl->mpRealParent = pBorderWin->mpWindowImpl->mpParent;
2009 // reparent us above the border window
2010 SetParent( pBorderWin->mpWindowImpl->mpParent );
2011 // set us to the position and size of our previous border
2012 Point aBorderPos( pBorderWin->GetPosPixel() );
2013 Size aBorderSize( pBorderWin->GetSizePixel() );
2014 setPosSizePixel( aBorderPos.X(), aBorderPos.Y(), aBorderSize.Width(), aBorderSize.Height() );
2015 // release border window
2016 pBorderWin.disposeAndClear();
2018 // set new style bits
2019 SetStyle( GetStyle() & (~WB_BORDER) );
2021 else
2023 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2024 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetBorderStyle( nBorderStyle );
2025 else
2026 mpWindowImpl->mpBorderWindow->SetBorderStyle( nBorderStyle );
2030 WindowBorderStyle Window::GetBorderStyle() const
2033 if ( mpWindowImpl->mpBorderWindow )
2035 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2036 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorderStyle();
2037 else
2038 return mpWindowImpl->mpBorderWindow->GetBorderStyle();
2041 return WindowBorderStyle::NONE;
2044 tools::Long Window::CalcTitleWidth() const
2047 if ( mpWindowImpl->mpBorderWindow )
2049 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2050 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->CalcTitleWidth();
2051 else
2052 return mpWindowImpl->mpBorderWindow->CalcTitleWidth();
2054 else if ( mpWindowImpl->mbFrame && (mpWindowImpl->mnStyle & WB_MOVEABLE) )
2056 // we guess the width for frame windows as we do not know the
2057 // border of external dialogs
2058 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2059 vcl::Font aFont = GetFont();
2060 const_cast<vcl::Window*>(this)->SetPointFont(*const_cast<Window*>(this), rStyleSettings.GetTitleFont());
2061 tools::Long nTitleWidth = GetTextWidth( GetText() );
2062 const_cast<vcl::Window*>(this)->SetFont( aFont );
2063 nTitleWidth += rStyleSettings.GetTitleHeight() * 3;
2064 nTitleWidth += StyleSettings::GetBorderSize() * 2;
2065 nTitleWidth += 10;
2066 return nTitleWidth;
2069 return 0;
2072 void Window::SetInputContext( const InputContext& rInputContext )
2075 mpWindowImpl->maInputContext = rInputContext;
2076 if ( !mpWindowImpl->mbInFocusHdl && HasFocus() )
2077 ImplNewInputContext();
2080 void Window::PostExtTextInputEvent(VclEventId nType, const OUString& rText)
2082 switch (nType)
2084 case VclEventId::ExtTextInput:
2086 std::unique_ptr<ExtTextInputAttr[]> pAttr(new ExtTextInputAttr[rText.getLength()]);
2087 for (int i = 0; i < rText.getLength(); ++i) {
2088 pAttr[i] = ExtTextInputAttr::Underline;
2090 SalExtTextInputEvent aEvent { rText, pAttr.get(), rText.getLength(), EXTTEXTINPUT_CURSOR_OVERWRITE };
2091 ImplWindowFrameProc(this, SalEvent::ExtTextInput, &aEvent);
2093 break;
2094 case VclEventId::EndExtTextInput:
2095 ImplWindowFrameProc(this, SalEvent::EndExtTextInput, nullptr);
2096 break;
2097 default:
2098 assert(false);
2102 void Window::EndExtTextInput()
2104 if ( mpWindowImpl->mbExtTextInput )
2105 ImplGetFrame()->EndExtTextInput( EndExtTextInputFlags::Complete );
2108 void Window::SetCursorRect( const tools::Rectangle* pRect, tools::Long nExtTextInputWidth )
2111 ImplWinData* pWinData = ImplGetWinData();
2112 if ( pWinData->mpCursorRect )
2114 if ( pRect )
2115 pWinData->mpCursorRect = *pRect;
2116 else
2117 pWinData->mpCursorRect.reset();
2119 else
2121 if ( pRect )
2122 pWinData->mpCursorRect = *pRect;
2125 pWinData->mnCursorExtWidth = nExtTextInputWidth;
2129 const tools::Rectangle* Window::GetCursorRect() const
2132 ImplWinData* pWinData = ImplGetWinData();
2133 return pWinData->mpCursorRect ? &*pWinData->mpCursorRect : nullptr;
2136 tools::Long Window::GetCursorExtTextInputWidth() const
2139 ImplWinData* pWinData = ImplGetWinData();
2140 return pWinData->mnCursorExtWidth;
2143 void Window::SetCompositionCharRect( const tools::Rectangle* pRect, tools::Long nCompositionLength, bool bVertical ) {
2145 ImplWinData* pWinData = ImplGetWinData();
2146 pWinData->mpCompositionCharRects.reset();
2147 pWinData->mbVertical = bVertical;
2148 pWinData->mnCompositionCharRects = nCompositionLength;
2149 if ( pRect && (nCompositionLength > 0) )
2151 pWinData->mpCompositionCharRects.reset( new tools::Rectangle[nCompositionLength] );
2152 for (tools::Long i = 0; i < nCompositionLength; ++i)
2153 pWinData->mpCompositionCharRects[i] = pRect[i];
2157 void Window::CollectChildren(::std::vector<vcl::Window *>& rAllChildren )
2159 rAllChildren.push_back( this );
2161 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2162 while ( pChild )
2164 pChild->CollectChildren( rAllChildren );
2165 pChild = pChild->mpWindowImpl->mpNext;
2169 void Window::SetPointFont(vcl::RenderContext& rRenderContext, const vcl::Font& rFont)
2171 vcl::Font aFont = rFont;
2172 ImplPointToLogic(rRenderContext, aFont);
2173 rRenderContext.SetFont(aFont);
2176 vcl::Font Window::GetPointFont(vcl::RenderContext const & rRenderContext) const
2178 vcl::Font aFont = rRenderContext.GetFont();
2179 ImplLogicToPoint(rRenderContext, aFont);
2180 return aFont;
2183 void Window::Show(bool bVisible, ShowFlags nFlags)
2185 if ( IsDisposed() || mpWindowImpl->mbVisible == bVisible )
2186 return;
2188 VclPtr<vcl::Window> xWindow(this);
2190 bool bRealVisibilityChanged = false;
2191 mpWindowImpl->mbVisible = bVisible;
2193 if ( !bVisible )
2195 ImplHideAllOverlaps();
2196 if( xWindow->IsDisposed() )
2197 return;
2199 if ( mpWindowImpl->mpBorderWindow )
2201 bool bOldUpdate = mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate;
2202 if ( mpWindowImpl->mbNoParentUpdate )
2203 mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = true;
2204 mpWindowImpl->mpBorderWindow->Show( false, nFlags );
2205 mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = bOldUpdate;
2207 else if ( mpWindowImpl->mbFrame )
2209 mpWindowImpl->mbSuppressAccessibilityEvents = true;
2210 mpWindowImpl->mpFrame->Show( false );
2213 CompatStateChanged( StateChangedType::Visible );
2215 if ( mpWindowImpl->mbReallyVisible )
2217 if ( mpWindowImpl->mbInitWinClipRegion )
2218 ImplInitWinClipRegion();
2220 vcl::Region aInvRegion = mpWindowImpl->maWinClipRegion;
2222 if( xWindow->IsDisposed() )
2223 return;
2225 bRealVisibilityChanged = mpWindowImpl->mbReallyVisible;
2226 ImplResetReallyVisible();
2227 ImplSetClipFlag();
2229 if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
2231 // convert focus
2232 if ( !(nFlags & ShowFlags::NoFocusChange) && HasChildPathFocus() )
2234 if ( mpWindowImpl->mpOverlapWindow->IsEnabled() &&
2235 mpWindowImpl->mpOverlapWindow->IsInputEnabled() &&
2236 ! mpWindowImpl->mpOverlapWindow->IsInModalMode()
2238 mpWindowImpl->mpOverlapWindow->GrabFocus();
2242 if ( !mpWindowImpl->mbFrame )
2244 if (mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mbEnableNativeWidget)
2247 * #i48371# native theming: some themes draw outside the control
2248 * area we tell them to (bad thing, but we cannot do much about it ).
2249 * On hiding these controls they get invalidated with their window rectangle
2250 * which leads to the parts outside the control area being left and not
2251 * invalidated. Workaround: invalidate an area on the parent, too
2253 const int workaround_border = 5;
2254 tools::Rectangle aBounds( aInvRegion.GetBoundRect() );
2255 aBounds.AdjustLeft( -workaround_border );
2256 aBounds.AdjustTop( -workaround_border );
2257 aBounds.AdjustRight(workaround_border );
2258 aBounds.AdjustBottom(workaround_border );
2259 aInvRegion = aBounds;
2261 if ( !mpWindowImpl->mbNoParentUpdate )
2263 if ( !aInvRegion.IsEmpty() )
2264 ImplInvalidateParentFrameRegion( aInvRegion );
2266 ImplGenerateMouseMove();
2270 else
2272 // inherit native widget flag for form controls
2273 // required here, because frames never show up in the child hierarchy - which should be fixed...
2274 // eg, the drop down of a combobox which is a system floating window
2275 if( mpWindowImpl->mbFrame && GetParent() && GetParent()->IsCompoundControl() &&
2276 GetParent()->IsNativeWidgetEnabled() != IsNativeWidgetEnabled() &&
2277 !(GetStyle() & WB_TOOLTIPWIN) )
2279 EnableNativeWidget( GetParent()->IsNativeWidgetEnabled() );
2282 if ( mpWindowImpl->mbCallMove )
2284 ImplCallMove();
2286 if ( mpWindowImpl->mbCallResize )
2288 ImplCallResize();
2291 CompatStateChanged( StateChangedType::Visible );
2293 vcl::Window* pTestParent;
2294 if ( ImplIsOverlapWindow() )
2295 pTestParent = mpWindowImpl->mpOverlapWindow;
2296 else
2297 pTestParent = ImplGetParent();
2298 if ( mpWindowImpl->mbFrame || pTestParent->mpWindowImpl->mbReallyVisible )
2300 // if a window becomes visible, send all child windows a StateChange,
2301 // such that these can initialise themselves
2302 ImplCallInitShow();
2304 // If it is a SystemWindow it automatically pops up on top of
2305 // all other windows if needed.
2306 if ( ImplIsOverlapWindow() && !(nFlags & ShowFlags::NoActivate) )
2308 ImplStartToTop(( nFlags & ShowFlags::ForegroundTask ) ? ToTopFlags::ForegroundTask : ToTopFlags::NONE );
2309 ImplFocusToTop( ToTopFlags::NONE, false );
2312 // adjust mpWindowImpl->mbReallyVisible
2313 bRealVisibilityChanged = !mpWindowImpl->mbReallyVisible;
2314 ImplSetReallyVisible();
2316 // assure clip rectangles will be recalculated
2317 ImplSetClipFlag();
2319 if ( !mpWindowImpl->mbFrame )
2321 InvalidateFlags nInvalidateFlags = InvalidateFlags::Children;
2322 if( ! IsPaintTransparent() )
2323 nInvalidateFlags |= InvalidateFlags::NoTransparent;
2324 ImplInvalidate( nullptr, nInvalidateFlags );
2325 ImplGenerateMouseMove();
2329 if ( mpWindowImpl->mpBorderWindow )
2330 mpWindowImpl->mpBorderWindow->Show( true, nFlags );
2331 else if ( mpWindowImpl->mbFrame )
2333 // #106431#, hide SplashScreen
2334 ImplSVData* pSVData = ImplGetSVData();
2335 if ( !pSVData->mpIntroWindow )
2337 // The right way would be just to call this (not even in the 'if')
2338 auto pApp = GetpApp();
2339 if ( pApp )
2340 pApp->InitFinished();
2342 else if ( !ImplIsWindowOrChild( pSVData->mpIntroWindow ) )
2344 // ... but the VCL splash is broken, and it needs this
2345 // (for ./soffice .uno:NewDoc)
2346 pSVData->mpIntroWindow->Hide();
2349 //SAL_WARN_IF( mpWindowImpl->mbSuppressAccessibilityEvents, "vcl", "Window::Show() - Frame reactivated");
2350 mpWindowImpl->mbSuppressAccessibilityEvents = false;
2352 mpWindowImpl->mbPaintFrame = true;
2353 if (!Application::IsHeadlessModeEnabled())
2355 bool bNoActivate(nFlags & (ShowFlags::NoActivate|ShowFlags::NoFocusChange));
2356 mpWindowImpl->mpFrame->Show( true, bNoActivate );
2358 if( xWindow->IsDisposed() )
2359 return;
2361 // Query the correct size of the window, if we are waiting for
2362 // a system resize
2363 if ( mpWindowImpl->mbWaitSystemResize )
2365 tools::Long nOutWidth;
2366 tools::Long nOutHeight;
2367 mpWindowImpl->mpFrame->GetClientSize( nOutWidth, nOutHeight );
2368 ImplHandleResize( this, nOutWidth, nOutHeight );
2371 if (mpWindowImpl->mpFrameData->mpBuffer && mpWindowImpl->mpFrameData->mpBuffer->GetOutputSizePixel() != GetOutputSizePixel())
2372 // Make sure that the buffer size matches the window size, even if no resize was needed.
2373 mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(GetOutputSizePixel());
2376 if( xWindow->IsDisposed() )
2377 return;
2379 ImplShowAllOverlaps();
2382 if( xWindow->IsDisposed() )
2383 return;
2385 // the SHOW/HIDE events also serve as indicators to send child creation/destroy events to the access bridge
2386 // However, the access bridge only uses this event if the data member is not NULL (it's kind of a hack that
2387 // we re-use the SHOW/HIDE events this way, with this particular semantics).
2388 // Since #104887#, the notifications for the access bridge are done in Impl(Set|Reset)ReallyVisible. Here, we
2389 // now only notify with a NULL data pointer, for all other clients except the access bridge.
2390 if ( !bRealVisibilityChanged )
2391 CallEventListeners( mpWindowImpl->mbVisible ? VclEventId::WindowShow : VclEventId::WindowHide );
2392 if( xWindow->IsDisposed() )
2393 return;
2397 Size Window::GetSizePixel() const
2399 if (!mpWindowImpl)
2401 SAL_WARN("vcl.layout", "WTF no windowimpl");
2402 return Size(0,0);
2405 // #i43257# trigger pending resize handler to assure correct window sizes
2406 if( mpWindowImpl->mpFrameData->maResizeIdle.IsActive() )
2408 VclPtr<vcl::Window> xWindow( const_cast<Window*>(this) );
2409 mpWindowImpl->mpFrameData->maResizeIdle.Stop();
2410 mpWindowImpl->mpFrameData->maResizeIdle.Invoke( nullptr );
2411 if( xWindow->IsDisposed() )
2412 return Size(0,0);
2415 return Size( mnOutWidth+mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder,
2416 mnOutHeight+mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder );
2419 void Window::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
2420 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
2422 rLeftBorder = mpWindowImpl->mnLeftBorder;
2423 rTopBorder = mpWindowImpl->mnTopBorder;
2424 rRightBorder = mpWindowImpl->mnRightBorder;
2425 rBottomBorder = mpWindowImpl->mnBottomBorder;
2428 void Window::Enable( bool bEnable, bool bChild )
2430 if ( IsDisposed() )
2431 return;
2433 if ( !bEnable )
2435 // the tracking mode will be stopped or the capture will be stolen
2436 // when a window is disabled,
2437 if ( IsTracking() )
2438 EndTracking( TrackingEventFlags::Cancel );
2439 if ( IsMouseCaptured() )
2440 ReleaseMouse();
2441 // try to pass focus to the next control
2442 // if the window has focus and is contained in the dialog control
2443 // mpWindowImpl->mbDisabled should only be set after a call of ImplDlgCtrlNextWindow().
2444 // Otherwise ImplDlgCtrlNextWindow() should be used
2445 if ( HasFocus() )
2446 ImplDlgCtrlNextWindow();
2449 if ( mpWindowImpl->mpBorderWindow )
2451 mpWindowImpl->mpBorderWindow->Enable( bEnable, false );
2452 if ( (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) &&
2453 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
2454 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->Enable( bEnable );
2457 // #i56102# restore app focus win in case the
2458 // window was disabled when the frame focus changed
2459 ImplSVData* pSVData = ImplGetSVData();
2460 if (bEnable && pSVData->mpWinData->mpFocusWin == nullptr
2461 && mpWindowImpl->mpFrameData->mbHasFocus && mpWindowImpl->mpFrameData->mpFocusWin == this)
2462 pSVData->mpWinData->mpFocusWin = this;
2464 if ( mpWindowImpl->mbDisabled != !bEnable )
2466 mpWindowImpl->mbDisabled = !bEnable;
2467 if ( mpWindowImpl->mpSysObj )
2468 mpWindowImpl->mpSysObj->Enable( bEnable && !mpWindowImpl->mbInputDisabled );
2469 CompatStateChanged( StateChangedType::Enable );
2471 CallEventListeners( bEnable ? VclEventId::WindowEnabled : VclEventId::WindowDisabled );
2474 if ( bChild )
2476 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2477 while ( pChild )
2479 pChild->Enable( bEnable, bChild );
2480 pChild = pChild->mpWindowImpl->mpNext;
2484 if ( IsReallyVisible() )
2485 ImplGenerateMouseMove();
2488 void Window::EnableInput( bool bEnable, bool bChild )
2490 if (!mpWindowImpl)
2491 return;
2493 if ( mpWindowImpl->mpBorderWindow )
2495 mpWindowImpl->mpBorderWindow->EnableInput( bEnable, false );
2496 if ( (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) &&
2497 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
2498 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->EnableInput( bEnable );
2501 if ( (!bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled) || bEnable )
2503 // automatically stop the tracking mode or steal capture
2504 // if the window is disabled
2505 if ( !bEnable )
2507 if ( IsTracking() )
2508 EndTracking( TrackingEventFlags::Cancel );
2509 if ( IsMouseCaptured() )
2510 ReleaseMouse();
2513 if ( mpWindowImpl->mbInputDisabled != !bEnable )
2515 mpWindowImpl->mbInputDisabled = !bEnable;
2516 if ( mpWindowImpl->mpSysObj )
2517 mpWindowImpl->mpSysObj->Enable( !mpWindowImpl->mbDisabled && bEnable );
2521 // #i56102# restore app focus win in case the
2522 // window was disabled when the frame focus changed
2523 ImplSVData* pSVData = ImplGetSVData();
2524 if (bEnable && pSVData->mpWinData->mpFocusWin == nullptr
2525 && mpWindowImpl->mpFrameData->mbHasFocus && mpWindowImpl->mpFrameData->mpFocusWin == this)
2526 pSVData->mpWinData->mpFocusWin = this;
2528 if ( bChild )
2530 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2531 while ( pChild )
2533 pChild->EnableInput( bEnable, bChild );
2534 pChild = pChild->mpWindowImpl->mpNext;
2538 if ( IsReallyVisible() )
2539 ImplGenerateMouseMove();
2542 void Window::EnableInput( bool bEnable, const vcl::Window* pExcludeWindow )
2544 if (!mpWindowImpl)
2545 return;
2547 EnableInput( bEnable );
2549 // pExecuteWindow is the first Overlap-Frame --> if this
2550 // shouldn't be the case, then this must be changed in dialog.cxx
2551 if( pExcludeWindow )
2552 pExcludeWindow = pExcludeWindow->ImplGetFirstOverlapWindow();
2553 vcl::Window* pSysWin = mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mpFirstOverlap;
2554 while ( pSysWin )
2556 // Is Window in the path from this window
2557 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pSysWin, true ) )
2559 // Is Window not in the exclude window path or not the
2560 // exclude window, then change the status
2561 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pSysWin, true ) )
2562 pSysWin->EnableInput( bEnable );
2564 pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
2567 // enable/disable floating system windows as well
2568 vcl::Window* pFrameWin = ImplGetSVData()->maFrameData.mpFirstFrame;
2569 while ( pFrameWin )
2571 if( pFrameWin->ImplIsFloatingWindow() )
2573 // Is Window in the path from this window
2574 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pFrameWin, true ) )
2576 // Is Window not in the exclude window path or not the
2577 // exclude window, then change the status
2578 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pFrameWin, true ) )
2579 pFrameWin->EnableInput( bEnable );
2582 pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
2585 // the same for ownerdraw floating windows
2586 if( !mpWindowImpl->mbFrame )
2587 return;
2589 ::std::vector< VclPtr<vcl::Window> >& rList = mpWindowImpl->mpFrameData->maOwnerDrawList;
2590 for (auto const& elem : rList)
2592 // Is Window in the path from this window
2593 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( elem, true ) )
2595 // Is Window not in the exclude window path or not the
2596 // exclude window, then change the status
2597 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( elem, true ) )
2598 elem->EnableInput( bEnable );
2603 void Window::AlwaysEnableInput( bool bAlways, bool bChild )
2606 if ( mpWindowImpl->mpBorderWindow )
2607 mpWindowImpl->mpBorderWindow->AlwaysEnableInput( bAlways, false );
2609 if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled )
2611 mpWindowImpl->meAlwaysInputMode = AlwaysInputEnabled;
2612 EnableInput(true, false);
2614 else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled )
2616 mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
2619 if ( bChild )
2621 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2622 while ( pChild )
2624 pChild->AlwaysEnableInput( bAlways, bChild );
2625 pChild = pChild->mpWindowImpl->mpNext;
2630 void Window::SetActivateMode( ActivateModeFlags nMode )
2633 if ( mpWindowImpl->mpBorderWindow )
2634 mpWindowImpl->mpBorderWindow->SetActivateMode( nMode );
2636 if ( mpWindowImpl->mnActivateMode == nMode )
2637 return;
2639 mpWindowImpl->mnActivateMode = nMode;
2641 // possibly trigger Deactivate/Activate
2642 if ( mpWindowImpl->mnActivateMode != ActivateModeFlags::NONE )
2644 if ( (mpWindowImpl->mbActive || (GetType() == WindowType::BORDERWINDOW)) &&
2645 !HasChildPathFocus( true ) )
2647 mpWindowImpl->mbActive = false;
2648 Deactivate();
2651 else
2653 if ( !mpWindowImpl->mbActive || (GetType() == WindowType::BORDERWINDOW) )
2655 mpWindowImpl->mbActive = true;
2656 Activate();
2661 void Window::setPosSizePixel( tools::Long nX, tools::Long nY,
2662 tools::Long nWidth, tools::Long nHeight, PosSizeFlags nFlags )
2664 bool bHasValidSize = !mpWindowImpl->mbDefSize;
2666 if ( nFlags & PosSizeFlags::Pos )
2667 mpWindowImpl->mbDefPos = false;
2668 if ( nFlags & PosSizeFlags::Size )
2669 mpWindowImpl->mbDefSize = false;
2671 // The top BorderWindow is the window which is to be positioned
2672 VclPtr<vcl::Window> pWindow = this;
2673 while ( pWindow->mpWindowImpl->mpBorderWindow )
2674 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
2676 if ( pWindow->mpWindowImpl->mbFrame )
2678 // Note: if we're positioning a frame, the coordinates are interpreted
2679 // as being the top-left corner of the window's client area and NOT
2680 // as the position of the border ! (due to limitations of several UNIX window managers)
2681 tools::Long nOldWidth = pWindow->mnOutWidth;
2683 if ( !(nFlags & PosSizeFlags::Width) )
2684 nWidth = pWindow->mnOutWidth;
2685 if ( !(nFlags & PosSizeFlags::Height) )
2686 nHeight = pWindow->mnOutHeight;
2688 sal_uInt16 nSysFlags=0;
2689 VclPtr<vcl::Window> pParent = GetParent();
2690 VclPtr<vcl::Window> pWinParent = pWindow->GetParent();
2692 if( nFlags & PosSizeFlags::Width )
2693 nSysFlags |= SAL_FRAME_POSSIZE_WIDTH;
2694 if( nFlags & PosSizeFlags::Height )
2695 nSysFlags |= SAL_FRAME_POSSIZE_HEIGHT;
2696 if( nFlags & PosSizeFlags::X )
2698 nSysFlags |= SAL_FRAME_POSSIZE_X;
2699 if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
2701 nX += pWinParent->mnOutOffX;
2703 if( pParent && pParent->ImplIsAntiparallel() )
2705 tools::Rectangle aRect( Point ( nX, nY ), Size( nWidth, nHeight ) );
2706 const OutputDevice *pParentOutDev = pParent->GetOutDev();
2707 pParentOutDev->ReMirror( aRect );
2708 nX = aRect.Left();
2711 if( !(nFlags & PosSizeFlags::X) && bHasValidSize && pWindow->mpWindowImpl->mpFrame->maGeometry.nWidth )
2713 // RTL: make sure the old right aligned position is not changed
2714 // system windows will always grow to the right
2715 if ( pWinParent )
2717 OutputDevice *pParentOutDev = pWinParent->GetOutDev();
2718 if( pParentOutDev->HasMirroredGraphics() )
2720 const SalFrameGeometry& aSysGeometry = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2721 const SalFrameGeometry& aParentSysGeometry =
2722 pWinParent->mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2723 tools::Long myWidth = nOldWidth;
2724 if( !myWidth )
2725 myWidth = aSysGeometry.nWidth;
2726 if( !myWidth )
2727 myWidth = nWidth;
2728 nFlags |= PosSizeFlags::X;
2729 nSysFlags |= SAL_FRAME_POSSIZE_X;
2730 nX = aParentSysGeometry.nX - aSysGeometry.nLeftDecoration + aParentSysGeometry.nWidth
2731 - myWidth - 1 - aSysGeometry.nX;
2735 if( nFlags & PosSizeFlags::Y )
2737 nSysFlags |= SAL_FRAME_POSSIZE_Y;
2738 if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
2740 nY += pWinParent->mnOutOffY;
2744 if( nSysFlags & (SAL_FRAME_POSSIZE_WIDTH|SAL_FRAME_POSSIZE_HEIGHT) )
2746 // check for min/max client size and adjust size accordingly
2747 // otherwise it may happen that the resize event is ignored, i.e. the old size remains
2748 // unchanged but ImplHandleResize() is called with the wrong size
2749 SystemWindow *pSystemWindow = dynamic_cast< SystemWindow* >( pWindow.get() );
2750 if( pSystemWindow )
2752 Size aMinSize = pSystemWindow->GetMinOutputSizePixel();
2753 Size aMaxSize = pSystemWindow->GetMaxOutputSizePixel();
2754 if( nWidth < aMinSize.Width() )
2755 nWidth = aMinSize.Width();
2756 if( nHeight < aMinSize.Height() )
2757 nHeight = aMinSize.Height();
2759 if( nWidth > aMaxSize.Width() )
2760 nWidth = aMaxSize.Width();
2761 if( nHeight > aMaxSize.Height() )
2762 nHeight = aMaxSize.Height();
2766 pWindow->mpWindowImpl->mpFrame->SetPosSize( nX, nY, nWidth, nHeight, nSysFlags );
2768 // Adjust resize with the hack of different client size and frame geometries to fix
2769 // native menu bars. Eventually this should be replaced by proper mnTopBorder usage.
2770 pWindow->mpWindowImpl->mpFrame->GetClientSize(nWidth, nHeight);
2772 // Resize should be called directly. If we haven't
2773 // set the correct size, we get a second resize from
2774 // the system with the correct size. This can be happened
2775 // if the size is too small or too large.
2776 ImplHandleResize( pWindow, nWidth, nHeight );
2778 else
2780 pWindow->ImplPosSizeWindow( nX, nY, nWidth, nHeight, nFlags );
2781 if ( IsReallyVisible() )
2782 ImplGenerateMouseMove();
2786 Point Window::GetPosPixel() const
2788 return mpWindowImpl->maPos;
2791 tools::Rectangle Window::GetDesktopRectPixel() const
2793 tools::Rectangle rRect;
2794 mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrame->GetWorkArea( rRect );
2795 return rRect;
2798 Point Window::OutputToScreenPixel( const Point& rPos ) const
2800 // relative to top level parent
2801 return Point( rPos.X()+mnOutOffX, rPos.Y()+mnOutOffY );
2804 Point Window::ScreenToOutputPixel( const Point& rPos ) const
2806 // relative to top level parent
2807 return Point( rPos.X()-mnOutOffX, rPos.Y()-mnOutOffY );
2810 tools::Long Window::ImplGetUnmirroredOutOffX()
2812 // revert mnOutOffX changes that were potentially made in ImplPosSizeWindow
2813 tools::Long offx = mnOutOffX;
2814 OutputDevice *pOutDev = GetOutDev();
2815 if( pOutDev->HasMirroredGraphics() )
2817 if( mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
2819 if ( !ImplIsOverlapWindow() )
2820 offx -= mpWindowImpl->mpParent->mnOutOffX;
2822 offx = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - offx;
2824 if ( !ImplIsOverlapWindow() )
2825 offx += mpWindowImpl->mpParent->mnOutOffX;
2829 return offx;
2832 // normalized screen pixel are independent of mirroring
2833 Point Window::OutputToNormalizedScreenPixel( const Point& rPos ) const
2835 // relative to top level parent
2836 tools::Long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX();
2837 return Point( rPos.X()+offx, rPos.Y()+mnOutOffY );
2840 Point Window::NormalizedScreenToOutputPixel( const Point& rPos ) const
2842 // relative to top level parent
2843 tools::Long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX();
2844 return Point( rPos.X()-offx, rPos.Y()-mnOutOffY );
2847 Point Window::OutputToAbsoluteScreenPixel( const Point& rPos ) const
2849 // relative to the screen
2850 Point p = OutputToScreenPixel( rPos );
2851 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2852 p.AdjustX(g.nX );
2853 p.AdjustY(g.nY );
2854 return p;
2857 Point Window::AbsoluteScreenToOutputPixel( const Point& rPos ) const
2859 // relative to the screen
2860 Point p = ScreenToOutputPixel( rPos );
2861 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2862 p.AdjustX( -(g.nX) );
2863 p.AdjustY( -(g.nY) );
2864 return p;
2867 tools::Rectangle Window::ImplOutputToUnmirroredAbsoluteScreenPixel( const tools::Rectangle &rRect ) const
2869 // this method creates unmirrored screen coordinates to be compared with the desktop
2870 // and is used for positioning of RTL popup windows correctly on the screen
2871 SalFrameGeometry g = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2873 Point p1 = OutputToScreenPixel( rRect.TopRight() );
2874 p1.setX( g.nX+g.nWidth-p1.X() );
2875 p1.AdjustY(g.nY );
2877 Point p2 = OutputToScreenPixel( rRect.BottomLeft() );
2878 p2.setX( g.nX+g.nWidth-p2.X() );
2879 p2.AdjustY(g.nY );
2881 return tools::Rectangle( p1, p2 );
2884 tools::Rectangle Window::GetWindowExtentsRelative(const vcl::Window *pRelativeWindow) const
2886 // with decoration
2887 return ImplGetWindowExtentsRelative( pRelativeWindow );
2890 tools::Rectangle Window::ImplGetWindowExtentsRelative(const vcl::Window *pRelativeWindow) const
2892 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2893 // make sure we use the extent of our border window,
2894 // otherwise we miss a few pixels
2895 const vcl::Window *pWin = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow : this;
2897 Point aPos( pWin->OutputToScreenPixel( Point(0,0) ) );
2898 aPos.AdjustX(g.nX );
2899 aPos.AdjustY(g.nY );
2900 Size aSize ( pWin->GetSizePixel() );
2901 // #104088# do not add decoration to the workwindow to be compatible to java accessibility api
2902 if( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && GetType() != WindowType::WORKWINDOW) )
2904 aPos.AdjustX( -sal_Int32(g.nLeftDecoration) );
2905 aPos.AdjustY( -sal_Int32(g.nTopDecoration) );
2906 aSize.AdjustWidth(g.nLeftDecoration + g.nRightDecoration );
2907 aSize.AdjustHeight(g.nTopDecoration + g.nBottomDecoration );
2909 if( pRelativeWindow )
2911 // #106399# express coordinates relative to borderwindow
2912 const vcl::Window *pRelWin = pRelativeWindow->mpWindowImpl->mpBorderWindow ? pRelativeWindow->mpWindowImpl->mpBorderWindow.get() : pRelativeWindow;
2913 aPos = pRelWin->AbsoluteScreenToOutputPixel( aPos );
2915 return tools::Rectangle( aPos, aSize );
2918 void Window::Scroll( tools::Long nHorzScroll, tools::Long nVertScroll, ScrollFlags nFlags )
2921 ImplScroll( tools::Rectangle( Point( mnOutOffX, mnOutOffY ),
2922 Size( mnOutWidth, mnOutHeight ) ),
2923 nHorzScroll, nVertScroll, nFlags & ~ScrollFlags::Clip );
2926 void Window::Scroll( tools::Long nHorzScroll, tools::Long nVertScroll,
2927 const tools::Rectangle& rRect, ScrollFlags nFlags )
2929 OutputDevice *pOutDev = GetOutDev();
2930 tools::Rectangle aRect = pOutDev->ImplLogicToDevicePixel( rRect );
2931 aRect.Intersection( tools::Rectangle( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ) );
2932 if ( !aRect.IsEmpty() )
2933 ImplScroll( aRect, nHorzScroll, nVertScroll, nFlags );
2936 void Window::Flush()
2938 if (mpWindowImpl)
2940 const tools::Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
2941 mpWindowImpl->mpFrame->Flush( aWinRect );
2945 void Window::SetUpdateMode( bool bUpdate )
2947 if (mpWindowImpl)
2949 mpWindowImpl->mbNoUpdate = !bUpdate;
2950 CompatStateChanged( StateChangedType::UpdateMode );
2954 void Window::GrabFocus()
2956 ImplGrabFocus( GetFocusFlags::NONE );
2959 bool Window::HasFocus() const
2961 return (this == ImplGetSVData()->mpWinData->mpFocusWin);
2964 void Window::GrabFocusToDocument()
2966 ImplGrabFocusToDocument(GetFocusFlags::NONE);
2969 VclPtr<vcl::Window> Window::GetFocusedWindow() const
2971 if (mpWindowImpl && mpWindowImpl->mpFrameData)
2972 return mpWindowImpl->mpFrameData->mpFocusWin;
2973 else
2974 return VclPtr<vcl::Window>();
2977 void Window::SetFakeFocus( bool bFocus )
2979 ImplGetWindowImpl()->mbFakeFocusSet = bFocus;
2982 bool Window::HasChildPathFocus( bool bSystemWindow ) const
2985 vcl::Window* pFocusWin = ImplGetSVData()->mpWinData->mpFocusWin;
2986 if ( pFocusWin )
2987 return ImplIsWindowOrChild( pFocusWin, bSystemWindow );
2988 return false;
2991 void Window::SetCursor( vcl::Cursor* pCursor )
2994 if ( mpWindowImpl->mpCursor != pCursor )
2996 if ( mpWindowImpl->mpCursor )
2997 mpWindowImpl->mpCursor->ImplHide();
2998 mpWindowImpl->mpCursor = pCursor;
2999 if ( pCursor )
3000 pCursor->ImplShow();
3004 void Window::SetText( const OUString& rStr )
3006 if (!mpWindowImpl || rStr == mpWindowImpl->maText)
3007 return;
3009 OUString oldTitle( mpWindowImpl->maText );
3010 mpWindowImpl->maText = rStr;
3012 if ( mpWindowImpl->mpBorderWindow )
3013 mpWindowImpl->mpBorderWindow->SetText( rStr );
3014 else if ( mpWindowImpl->mbFrame )
3015 mpWindowImpl->mpFrame->SetTitle( rStr );
3017 CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle );
3019 // #107247# needed for accessibility
3020 // The VclEventId::WindowFrameTitleChanged is (mis)used to notify accessible name changes.
3021 // Therefore a window, which is labeled by this window, must also notify an accessible
3022 // name change.
3023 if ( IsReallyVisible() )
3025 vcl::Window* pWindow = GetAccessibleRelationLabelFor();
3026 if ( pWindow && pWindow != this )
3027 pWindow->CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle );
3030 CompatStateChanged( StateChangedType::Text );
3033 OUString Window::GetText() const
3036 return mpWindowImpl->maText;
3039 OUString Window::GetDisplayText() const
3042 return GetText();
3045 const Wallpaper& Window::GetDisplayBackground() const
3047 // FIXME: fix issue 52349, need to fix this really in
3048 // all NWF enabled controls
3049 const ToolBox* pTB = dynamic_cast<const ToolBox*>(this);
3050 if( pTB && IsNativeWidgetEnabled() )
3051 return pTB->ImplGetToolBoxPrivateData()->maDisplayBackground;
3053 if( !IsBackground() )
3055 if( mpWindowImpl->mpParent )
3056 return mpWindowImpl->mpParent->GetDisplayBackground();
3059 const Wallpaper& rBack = GetBackground();
3060 if( ! rBack.IsBitmap() &&
3061 ! rBack.IsGradient() &&
3062 rBack.GetColor()== COL_TRANSPARENT &&
3063 mpWindowImpl->mpParent )
3064 return mpWindowImpl->mpParent->GetDisplayBackground();
3065 return rBack;
3068 const OUString& Window::GetHelpText() const
3070 OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
3071 bool bStrHelpId = !aStrHelpId.isEmpty();
3073 if ( !mpWindowImpl->maHelpText.getLength() && bStrHelpId )
3075 if ( !IsDialog() && (mpWindowImpl->mnType != WindowType::TABPAGE) && (mpWindowImpl->mnType != WindowType::FLOATINGWINDOW) )
3077 Help* pHelp = Application::GetHelp();
3078 if ( pHelp )
3080 mpWindowImpl->maHelpText = pHelp->GetHelpText(aStrHelpId, this);
3081 mpWindowImpl->mbHelpTextDynamic = false;
3085 else if( mpWindowImpl->mbHelpTextDynamic && bStrHelpId )
3087 static const char* pEnv = getenv( "HELP_DEBUG" );
3088 if( pEnv && *pEnv )
3090 OUString aTxt = mpWindowImpl->maHelpText + "\n------------------\n" + aStrHelpId;
3091 mpWindowImpl->maHelpText = aTxt;
3093 mpWindowImpl->mbHelpTextDynamic = false;
3096 //Fallback to Window::GetAccessibleDescription without reentry to GetHelpText()
3097 if (mpWindowImpl->maHelpText.isEmpty() && mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleDescription)
3098 return *mpWindowImpl->mpAccessibleInfos->pAccessibleDescription;
3099 return mpWindowImpl->maHelpText;
3102 void Window::SetWindowPeer( Reference< css::awt::XWindowPeer > const & xPeer, VCLXWindow* pVCLXWindow )
3104 if (!mpWindowImpl)
3105 return;
3107 // be safe against re-entrance: first clear the old ref, then assign the new one
3108 mpWindowImpl->mxWindowPeer.clear();
3109 mpWindowImpl->mxWindowPeer = xPeer;
3111 mpWindowImpl->mpVCLXWindow = pVCLXWindow;
3114 Reference< css::awt::XWindowPeer > Window::GetComponentInterface( bool bCreate )
3116 if ( !mpWindowImpl->mxWindowPeer.is() && bCreate )
3118 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
3119 if ( pWrapper )
3120 mpWindowImpl->mxWindowPeer = pWrapper->GetWindowInterface( this );
3122 return mpWindowImpl->mxWindowPeer;
3125 void Window::SetComponentInterface( Reference< css::awt::XWindowPeer > const & xIFace )
3127 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
3128 SAL_WARN_IF( !pWrapper, "vcl.window", "SetComponentInterface: No Wrapper!" );
3129 if ( pWrapper )
3130 pWrapper->SetWindowInterface( this, xIFace );
3133 typedef std::map<vcl::LOKWindowId, VclPtr<vcl::Window>> LOKWindowsMap;
3135 namespace {
3137 LOKWindowsMap& GetLOKWindowsMap()
3139 // Map to remember the LOKWindowId <-> Window binding.
3140 static LOKWindowsMap s_aLOKWindowsMap;
3142 return s_aLOKWindowsMap;
3147 void Window::SetLOKNotifier(const vcl::ILibreOfficeKitNotifier* pNotifier, bool bParent)
3149 // don't allow setting this twice
3150 assert(mpWindowImpl->mpLOKNotifier == nullptr);
3151 assert(pNotifier);
3152 // never use this in the desktop case
3153 assert(comphelper::LibreOfficeKit::isActive());
3155 if (!bParent)
3157 // Counter to be able to have unique id's for each window.
3158 static vcl::LOKWindowId sLastLOKWindowId = 1;
3160 // assign the LOK window id
3161 assert(mpWindowImpl->mnLOKWindowId == 0);
3162 mpWindowImpl->mnLOKWindowId = sLastLOKWindowId++;
3163 GetLOKWindowsMap().emplace(mpWindowImpl->mnLOKWindowId, this);
3165 else
3166 mpWindowImpl->mbLOKParentNotifier = true;
3168 mpWindowImpl->mpLOKNotifier = pNotifier;
3171 VclPtr<Window> Window::FindLOKWindow(vcl::LOKWindowId nWindowId)
3173 const auto it = GetLOKWindowsMap().find(nWindowId);
3174 if (it != GetLOKWindowsMap().end())
3175 return it->second;
3177 return VclPtr<Window>();
3180 bool Window::IsLOKWindowsEmpty()
3182 return GetLOKWindowsMap().empty();
3185 void Window::ReleaseLOKNotifier()
3187 // unregister the LOK window binding
3188 if (mpWindowImpl->mnLOKWindowId > 0)
3189 GetLOKWindowsMap().erase(mpWindowImpl->mnLOKWindowId);
3191 mpWindowImpl->mpLOKNotifier = nullptr;
3192 mpWindowImpl->mnLOKWindowId = 0;
3195 ILibreOfficeKitNotifier::~ILibreOfficeKitNotifier()
3197 if (!comphelper::LibreOfficeKit::isActive())
3199 return;
3202 for (auto it = GetLOKWindowsMap().begin(); it != GetLOKWindowsMap().end();)
3204 WindowImpl* pWindowImpl = it->second->ImplGetWindowImpl();
3205 if (pWindowImpl && pWindowImpl->mpLOKNotifier == this)
3207 pWindowImpl->mpLOKNotifier = nullptr;
3208 pWindowImpl->mnLOKWindowId = 0;
3209 it = GetLOKWindowsMap().erase(it);
3210 continue;
3213 ++it;
3217 const vcl::ILibreOfficeKitNotifier* Window::GetLOKNotifier() const
3219 return mpWindowImpl->mpLOKNotifier;
3222 vcl::LOKWindowId Window::GetLOKWindowId() const
3224 return mpWindowImpl->mnLOKWindowId;
3227 VclPtr<vcl::Window> Window::GetParentWithLOKNotifier()
3229 VclPtr<vcl::Window> pWindow(this);
3231 while (pWindow && !pWindow->GetLOKNotifier())
3232 pWindow = pWindow->GetParent();
3234 return pWindow;
3237 namespace
3240 const char* windowTypeName(WindowType nWindowType)
3242 switch (nWindowType)
3244 case WindowType::NONE: return "none";
3245 case WindowType::MESSBOX: return "messagebox";
3246 case WindowType::INFOBOX: return "infobox";
3247 case WindowType::WARNINGBOX: return "warningbox";
3248 case WindowType::ERRORBOX: return "errorbox";
3249 case WindowType::QUERYBOX: return "querybox";
3250 case WindowType::WINDOW: return "window";
3251 case WindowType::WORKWINDOW: return "workwindow";
3252 case WindowType::CONTAINER: return "container";
3253 case WindowType::FLOATINGWINDOW: return "floatingwindow";
3254 case WindowType::DIALOG: return "dialog";
3255 case WindowType::MODELESSDIALOG: return "modelessdialog";
3256 case WindowType::CONTROL: return "control";
3257 case WindowType::PUSHBUTTON: return "pushbutton";
3258 case WindowType::OKBUTTON: return "okbutton";
3259 case WindowType::CANCELBUTTON: return "cancelbutton";
3260 case WindowType::HELPBUTTON: return "helpbutton";
3261 case WindowType::IMAGEBUTTON: return "imagebutton";
3262 case WindowType::MENUBUTTON: return "menubutton";
3263 case WindowType::MOREBUTTON: return "morebutton";
3264 case WindowType::SPINBUTTON: return "spinbutton";
3265 case WindowType::RADIOBUTTON: return "radiobutton";
3266 case WindowType::CHECKBOX: return "checkbox";
3267 case WindowType::TRISTATEBOX: return "tristatebox";
3268 case WindowType::EDIT: return "edit";
3269 case WindowType::MULTILINEEDIT: return "multilineedit";
3270 case WindowType::COMBOBOX: return "combobox";
3271 case WindowType::LISTBOX: return "listbox";
3272 case WindowType::MULTILISTBOX: return "multilistbox";
3273 case WindowType::FIXEDTEXT: return "fixedtext";
3274 case WindowType::FIXEDLINE: return "fixedline";
3275 case WindowType::FIXEDBITMAP: return "fixedbitmap";
3276 case WindowType::FIXEDIMAGE: return "fixedimage";
3277 case WindowType::GROUPBOX: return "groupbox";
3278 case WindowType::SCROLLBAR: return "scrollbar";
3279 case WindowType::SCROLLBARBOX: return "scrollbarbox";
3280 case WindowType::SPLITTER: return "splitter";
3281 case WindowType::SPLITWINDOW: return "splitwindow";
3282 case WindowType::SPINFIELD: return "spinfield";
3283 case WindowType::PATTERNFIELD: return "patternfield";
3284 case WindowType::METRICFIELD: return "metricfield";
3285 case WindowType::FORMATTEDFIELD: return "formattedfield";
3286 case WindowType::CURRENCYFIELD: return "currencyfield";
3287 case WindowType::DATEFIELD: return "datefield";
3288 case WindowType::TIMEFIELD: return "timefield";
3289 case WindowType::PATTERNBOX: return "patternbox";
3290 case WindowType::NUMERICBOX: return "numericbox";
3291 case WindowType::METRICBOX: return "metricbox";
3292 case WindowType::CURRENCYBOX: return "currencybox";
3293 case WindowType::DATEBOX: return "datebox";
3294 case WindowType::TIMEBOX: return "timebox";
3295 case WindowType::LONGCURRENCYBOX: return "longcurrencybox";
3296 case WindowType::SCROLLWINDOW: return "scrollwindow";
3297 case WindowType::TOOLBOX: return "toolbox";
3298 case WindowType::DOCKINGWINDOW: return "dockingwindow";
3299 case WindowType::STATUSBAR: return "statusbar";
3300 case WindowType::TABPAGE: return "tabpage";
3301 case WindowType::TABCONTROL: return "tabcontrol";
3302 case WindowType::TABDIALOG: return "tabdialog";
3303 case WindowType::BORDERWINDOW: return "borderwindow";
3304 case WindowType::BUTTONDIALOG: return "buttondialog";
3305 case WindowType::SYSTEMCHILDWINDOW: return "systemchildwindow";
3306 case WindowType::SLIDER: return "slider";
3307 case WindowType::MENUBARWINDOW: return "menubarwindow";
3308 case WindowType::TREELISTBOX: return "treelistbox";
3309 case WindowType::HELPTEXTWINDOW: return "helptextwindow";
3310 case WindowType::INTROWINDOW: return "introwindow";
3311 case WindowType::LISTBOXWINDOW: return "listboxwindow";
3312 case WindowType::DOCKINGAREA: return "dockingarea";
3313 case WindowType::RULER: return "ruler";
3314 case WindowType::HEADERBAR: return "headerbar";
3315 case WindowType::VERTICALTABCONTROL: return "verticaltabcontrol";
3317 // nothing to do here, but for completeness
3318 case WindowType::TOOLKIT_FRAMEWINDOW: return "toolkit_framewindow";
3319 case WindowType::TOOLKIT_SYSTEMCHILDWINDOW: return "toolkit_systemchildwindow";
3322 return "none";
3327 void Window::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
3329 rJsonWriter.put("id", get_id()); // TODO could be missing - sort out
3330 rJsonWriter.put("type", windowTypeName(GetType()));
3331 rJsonWriter.put("text", GetText());
3332 rJsonWriter.put("enabled", IsEnabled());
3334 if (vcl::Window* pChild = mpWindowImpl->mpFirstChild)
3336 auto childrenNode = rJsonWriter.startNode("children");
3337 while (pChild)
3339 if (pChild->IsVisible()) {
3340 auto childNode = rJsonWriter.startNode("");
3341 pChild->DumpAsPropertyTree(rJsonWriter);
3342 sal_Int32 nLeft = pChild->get_grid_left_attach();
3343 sal_Int32 nTop = pChild->get_grid_top_attach();
3344 if (nLeft != -1 && nTop != -1)
3346 rJsonWriter.put("left", nLeft);
3347 rJsonWriter.put("top", nTop);
3350 pChild = pChild->mpWindowImpl->mpNext;
3354 mpWindowImpl->maDumpAsPropertyTreeHdl.Call(rJsonWriter);
3357 void Window::ImplCallDeactivateListeners( vcl::Window *pNew )
3359 // no deactivation if the newly activated window is my child
3360 if ( !pNew || !ImplIsChild( pNew ) )
3362 VclPtr<vcl::Window> xWindow(this);
3363 CallEventListeners( VclEventId::WindowDeactivate, pNew );
3364 if( xWindow->IsDisposed() )
3365 return;
3367 // #100759#, avoid walking the wrong frame's hierarchy
3368 // eg, undocked docking windows (ImplDockFloatWin)
3369 if ( ImplGetParent() && mpWindowImpl->mpFrameWindow == ImplGetParent()->mpWindowImpl->mpFrameWindow )
3370 ImplGetParent()->ImplCallDeactivateListeners( pNew );
3374 void Window::ImplCallActivateListeners( vcl::Window *pOld )
3376 // no activation if the old active window is my child
3377 if ( pOld && ImplIsChild( pOld ))
3378 return;
3380 VclPtr<vcl::Window> xWindow(this);
3381 CallEventListeners( VclEventId::WindowActivate, pOld );
3382 if( xWindow->IsDisposed() )
3383 return;
3385 if ( ImplGetParent() )
3386 ImplGetParent()->ImplCallActivateListeners( pOld );
3387 else if( (mpWindowImpl->mnStyle & WB_INTROWIN) == 0 )
3389 // top level frame reached: store hint for DefModalDialogParent
3390 ImplGetSVData()->maFrameData.mpActiveApplicationFrame = mpWindowImpl->mpFrameWindow;
3394 void Window::SetClipboard(Reference<XClipboard> const & xClipboard)
3396 if (mpWindowImpl->mpFrameData)
3397 mpWindowImpl->mpFrameData->mxClipboard = xClipboard;
3400 Reference< XClipboard > Window::GetClipboard()
3402 if (!mpWindowImpl->mpFrameData)
3403 return static_cast<XClipboard*>(nullptr);
3404 if (!mpWindowImpl->mpFrameData->mxClipboard.is())
3405 mpWindowImpl->mpFrameData->mxClipboard = GetSystemClipboard();
3406 return mpWindowImpl->mpFrameData->mxClipboard;
3409 Reference< XClipboard > Window::GetPrimarySelection()
3411 if (!mpWindowImpl->mpFrameData)
3412 return static_cast<XClipboard*>(nullptr);
3413 if (!mpWindowImpl->mpFrameData->mxSelection.is())
3414 mpWindowImpl->mpFrameData->mxSelection = GetSystemPrimarySelection();
3415 return mpWindowImpl->mpFrameData->mxSelection;
3418 void Window::RecordLayoutData( vcl::ControlLayoutData* pLayout, const tools::Rectangle& rRect )
3420 assert(mpOutDevData);
3421 mpOutDevData->mpRecordLayout = pLayout;
3422 mpOutDevData->maRecordRect = rRect;
3423 Paint(*this, rRect);
3424 mpOutDevData->mpRecordLayout = nullptr;
3427 void Window::DrawSelectionBackground( const tools::Rectangle& rRect,
3428 sal_uInt16 highlight,
3429 bool bChecked,
3430 bool bDrawBorder
3433 if( rRect.IsEmpty() )
3434 return;
3436 const StyleSettings& rStyles = GetSettings().GetStyleSettings();
3438 // colors used for item highlighting
3439 Color aSelectionBorderCol( rStyles.GetHighlightColor() );
3440 Color aSelectionFillCol( aSelectionBorderCol );
3442 bool bDark = rStyles.GetFaceColor().IsDark();
3443 bool bBright = ( rStyles.GetFaceColor() == COL_WHITE );
3445 int c1 = aSelectionBorderCol.GetLuminance();
3446 int c2 = GetBackgroundColor().GetLuminance();
3448 if( !bDark && !bBright && abs( c2-c1 ) < 75 )
3450 // contrast too low
3451 sal_uInt16 h,s,b;
3452 aSelectionFillCol.RGBtoHSB( h, s, b );
3453 if( b > 50 ) b -= 40;
3454 else b += 40;
3455 aSelectionFillCol = Color::HSBtoRGB( h, s, b );
3456 aSelectionBorderCol = aSelectionFillCol;
3459 tools::Rectangle aRect( rRect );
3460 Color oldFillCol = GetFillColor();
3461 Color oldLineCol = GetLineColor();
3463 if( bDrawBorder )
3464 SetLineColor( bDark ? COL_WHITE : ( bBright ? COL_BLACK : aSelectionBorderCol ) );
3465 else
3466 SetLineColor();
3468 sal_uInt16 nPercent = 0;
3469 if( !highlight )
3471 if( bDark )
3472 aSelectionFillCol = COL_BLACK;
3473 else
3474 nPercent = 80; // just checked (light)
3476 else
3478 if( bChecked && highlight == 2 )
3480 if( bDark )
3481 aSelectionFillCol = COL_LIGHTGRAY;
3482 else if ( bBright )
3484 aSelectionFillCol = COL_BLACK;
3485 SetLineColor( COL_BLACK );
3486 nPercent = 0;
3488 else
3489 nPercent = 20; // selected, pressed or checked ( very dark )
3491 else if( bChecked || highlight == 1 )
3493 if( bDark )
3494 aSelectionFillCol = COL_GRAY;
3495 else if ( bBright )
3497 aSelectionFillCol = COL_BLACK;
3498 SetLineColor( COL_BLACK );
3499 nPercent = 0;
3501 else
3502 nPercent = 35; // selected, pressed or checked ( very dark )
3504 else
3506 if( bDark )
3507 aSelectionFillCol = COL_LIGHTGRAY;
3508 else if ( bBright )
3510 aSelectionFillCol = COL_BLACK;
3511 SetLineColor( COL_BLACK );
3512 if( highlight == 3 )
3513 nPercent = 80;
3514 else
3515 nPercent = 0;
3517 else
3518 nPercent = 70; // selected ( dark )
3522 SetFillColor( aSelectionFillCol );
3524 if( bDark )
3526 DrawRect( aRect );
3528 else
3530 tools::Polygon aPoly( aRect );
3531 tools::PolyPolygon aPolyPoly( aPoly );
3532 DrawTransparent( aPolyPoly, nPercent );
3535 SetFillColor( oldFillCol );
3536 SetLineColor( oldLineCol );
3539 bool Window::IsScrollable() const
3541 // check for scrollbars
3542 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
3543 while( pChild )
3545 if( pChild->GetType() == WindowType::SCROLLBAR )
3546 return true;
3547 else
3548 pChild = pChild->mpWindowImpl->mpNext;
3550 return false;
3553 void Window::ImplMirrorFramePos( Point &pt ) const
3555 pt.setX( mpWindowImpl->mpFrame->maGeometry.nWidth-1-pt.X() );
3558 // frame based modal counter (dialogs are not modal to the whole application anymore)
3559 bool Window::IsInModalMode() const
3561 return (mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mnModalMode != 0);
3564 void Window::IncModalCount()
3566 vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
3567 vcl::Window* pParent = pFrameWindow;
3568 while( pFrameWindow )
3570 pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode++;
3571 while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
3573 pParent = pParent->GetParent();
3575 pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
3578 void Window::DecModalCount()
3580 vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
3581 vcl::Window* pParent = pFrameWindow;
3582 while( pFrameWindow )
3584 pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode--;
3585 while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
3587 pParent = pParent->GetParent();
3589 pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
3593 void Window::ImplIsInTaskPaneList( bool mbIsInTaskList )
3595 mpWindowImpl->mbIsInTaskPaneList = mbIsInTaskList;
3598 void Window::ImplNotifyIconifiedState( bool bIconified )
3600 mpWindowImpl->mpFrameWindow->CallEventListeners( bIconified ? VclEventId::WindowMinimize : VclEventId::WindowNormalize );
3601 // #109206# notify client window as well to have toolkit topwindow listeners notified
3602 if( mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow && mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow )
3603 mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow->CallEventListeners( bIconified ? VclEventId::WindowMinimize : VclEventId::WindowNormalize );
3606 bool Window::HasActiveChildFrame() const
3608 bool bRet = false;
3609 vcl::Window *pFrameWin = ImplGetSVData()->maFrameData.mpFirstFrame;
3610 while( pFrameWin )
3612 if( pFrameWin != mpWindowImpl->mpFrameWindow )
3614 bool bDecorated = false;
3615 VclPtr< vcl::Window > pChildFrame = pFrameWin->ImplGetWindow();
3616 // #i15285# unfortunately WB_MOVEABLE is the same as WB_TABSTOP which can
3617 // be removed for ToolBoxes to influence the keyboard accessibility
3618 // thus WB_MOVEABLE is no indicator for decoration anymore
3619 // but FloatingWindows carry this information in their TitleType...
3620 // TODO: avoid duplicate WinBits !!!
3621 if( pChildFrame && pChildFrame->ImplIsFloatingWindow() )
3622 bDecorated = static_cast<FloatingWindow*>(pChildFrame.get())->GetTitleType() != FloatWinTitleType::NONE;
3623 if( bDecorated || (pFrameWin->mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) ) )
3624 if( pChildFrame && pChildFrame->IsVisible() && pChildFrame->IsActive() )
3626 if( ImplIsChild( pChildFrame, true ) )
3628 bRet = true;
3629 break;
3633 pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
3635 return bRet;
3638 LanguageType Window::GetInputLanguage() const
3640 return mpWindowImpl->mpFrame->GetInputLanguage();
3643 void Window::EnableNativeWidget( bool bEnable )
3645 static const char* pNoNWF = getenv( "SAL_NO_NWF" );
3646 if( pNoNWF && *pNoNWF )
3647 bEnable = false;
3649 if( bEnable != ImplGetWinData()->mbEnableNativeWidget )
3651 ImplGetWinData()->mbEnableNativeWidget = bEnable;
3653 // send datachanged event to allow for internal changes required for NWF
3654 // like clipmode, transparency, etc.
3655 DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, mxSettings.get(), AllSettingsFlags::STYLE );
3656 CompatDataChanged( aDCEvt );
3658 // sometimes the borderwindow is queried, so keep it in sync
3659 if( mpWindowImpl->mpBorderWindow )
3660 mpWindowImpl->mpBorderWindow->ImplGetWinData()->mbEnableNativeWidget = bEnable;
3663 // push down, useful for compound controls
3664 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
3665 while( pChild )
3667 pChild->EnableNativeWidget( bEnable );
3668 pChild = pChild->mpWindowImpl->mpNext;
3672 bool Window::IsNativeWidgetEnabled() const
3674 return ImplGetWinData()->mbEnableNativeWidget;
3677 Reference< css::rendering::XCanvas > Window::ImplGetCanvas( bool bSpriteCanvas ) const
3679 // try to retrieve hard reference from weak member
3680 Reference< css::rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
3682 // canvas still valid? Then we're done.
3683 if( xCanvas.is() )
3684 return xCanvas;
3686 Sequence< Any > aArg(5);
3688 // Feed any with operating system's window handle
3690 // common: first any is VCL pointer to window (for VCL canvas)
3691 aArg[ 0 ] <<= reinterpret_cast<sal_Int64>(this);
3692 aArg[ 1 ] <<= css::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
3693 aArg[ 2 ] <<= mpWindowImpl->mbAlwaysOnTop;
3694 aArg[ 3 ] <<= Reference< css::awt::XWindow >(
3695 const_cast<vcl::Window*>(this)->GetComponentInterface(),
3696 UNO_QUERY );
3697 aArg[ 4 ] = GetSystemGfxDataAny();
3699 Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
3701 // Create canvas instance with window handle
3703 static vcl::DeleteUnoReferenceOnDeinit<XMultiComponentFactory> xStaticCanvasFactory(
3704 css::rendering::CanvasFactory::create( xContext ) );
3705 Reference<XMultiComponentFactory> xCanvasFactory(xStaticCanvasFactory.get());
3707 if(xCanvasFactory.is())
3709 #ifdef _WIN32
3710 // see #140456# - if we're running on a multiscreen setup,
3711 // request special, multi-screen safe sprite canvas
3712 // implementation (not DX5 canvas, as it cannot cope with
3713 // surfaces spanning multiple displays). Note: canvas
3714 // (without sprite) stays the same)
3715 const sal_uInt32 nDisplay = static_cast< WinSalFrame* >( mpWindowImpl->mpFrame )->mnDisplay;
3716 if( nDisplay >= Application::GetScreenCount() )
3718 xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
3719 bSpriteCanvas ?
3720 OUString( "com.sun.star.rendering.SpriteCanvas.MultiScreen" ) :
3721 OUString( "com.sun.star.rendering.Canvas.MultiScreen" ),
3722 aArg,
3723 xContext ),
3724 UNO_QUERY );
3727 else
3728 #endif
3730 xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
3731 bSpriteCanvas ?
3732 OUString( "com.sun.star.rendering.SpriteCanvas" ) :
3733 OUString( "com.sun.star.rendering.Canvas" ),
3734 aArg,
3735 xContext ),
3736 UNO_QUERY );
3739 mpWindowImpl->mxCanvas = xCanvas;
3742 // no factory??? Empty reference, then.
3743 return xCanvas;
3746 Reference< css::rendering::XCanvas > Window::GetCanvas() const
3748 return ImplGetCanvas( false );
3751 Reference< css::rendering::XSpriteCanvas > Window::GetSpriteCanvas() const
3753 Reference< css::rendering::XSpriteCanvas > xSpriteCanvas(
3754 ImplGetCanvas( true ), UNO_QUERY );
3755 return xSpriteCanvas;
3758 OUString Window::GetSurroundingText() const
3760 return OUString();
3763 Selection Window::GetSurroundingTextSelection() const
3765 return Selection( 0, 0 );
3768 namespace
3770 using namespace com::sun::star;
3772 uno::Reference<accessibility::XAccessibleEditableText> lcl_GetxText(vcl::Window *pFocusWin)
3774 uno::Reference<accessibility::XAccessibleEditableText> xText;
3777 uno::Reference< accessibility::XAccessible > xAccessible( pFocusWin->GetAccessible() );
3778 if (xAccessible.is())
3779 xText = FindFocusedEditableText(xAccessible->getAccessibleContext());
3781 catch(const uno::Exception&)
3783 TOOLS_WARN_EXCEPTION( "vcl.gtk3", "Exception in getting input method surrounding text");
3785 return xText;
3789 // this is a rubbish implementation using a11y, ideally all subclasses implementing
3790 // GetSurroundingText/GetSurroundingTextSelection should implement this and then this
3791 // should be removed in favor of a stub that returns false
3792 bool Window::DeleteSurroundingText(const Selection& rSelection)
3794 uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText(this);
3795 if (xText.is())
3797 sal_Int32 nPosition = xText->getCaretPosition();
3798 // #i111768# range checking
3799 sal_Int32 nDeletePos = rSelection.Min();
3800 sal_Int32 nDeleteEnd = rSelection.Max();
3801 if (nDeletePos < 0)
3802 nDeletePos = 0;
3803 if (nDeleteEnd < 0)
3804 nDeleteEnd = 0;
3805 if (nDeleteEnd > xText->getCharacterCount())
3806 nDeleteEnd = xText->getCharacterCount();
3808 xText->deleteText(nDeletePos, nDeleteEnd);
3809 //tdf91641 adjust cursor if deleted chars shift it forward (normal case)
3810 if (nDeletePos < nPosition)
3812 if (nDeleteEnd <= nPosition)
3813 nPosition = nPosition - (nDeleteEnd - nDeletePos);
3814 else
3815 nPosition = nDeletePos;
3817 if (xText->getCharacterCount() >= nPosition)
3818 xText->setCaretPosition( nPosition );
3820 return true;
3823 return false;
3826 bool Window::UsePolyPolygonForComplexGradient()
3828 return meRasterOp != RasterOp::OverPaint;
3831 void Window::ApplySettings(vcl::RenderContext& /*rRenderContext*/)
3835 const SystemEnvData* Window::GetSystemData() const
3838 return mpWindowImpl->mpFrame ? mpWindowImpl->mpFrame->GetSystemData() : nullptr;
3841 bool Window::SupportsDoubleBuffering() const
3843 return mpWindowImpl->mpFrameData->mpBuffer;
3846 void Window::RequestDoubleBuffering(bool bRequest)
3848 if (bRequest)
3850 mpWindowImpl->mpFrameData->mpBuffer = VclPtrInstance<VirtualDevice>();
3851 // Make sure that the buffer size matches the frame size.
3852 mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(mpWindowImpl->mpFrameWindow->GetOutputSizePixel());
3854 else
3855 mpWindowImpl->mpFrameData->mpBuffer.reset();
3859 * The rationale here is that we moved destructors to
3860 * dispose and this altered a lot of code paths, that
3861 * are better left unchanged for now.
3863 #define COMPAT_BODY(method,args) \
3864 if (!mpWindowImpl || mpWindowImpl->mbInDispose) \
3865 Window::method args; \
3866 else \
3867 method args;
3869 void Window::CompatGetFocus()
3871 COMPAT_BODY(GetFocus,())
3874 void Window::CompatLoseFocus()
3876 COMPAT_BODY(LoseFocus,())
3879 void Window::CompatStateChanged( StateChangedType nStateChange )
3881 COMPAT_BODY(StateChanged,(nStateChange))
3884 void Window::CompatDataChanged( const DataChangedEvent& rDCEvt )
3886 COMPAT_BODY(DataChanged,(rDCEvt))
3889 bool Window::CompatPreNotify( NotifyEvent& rNEvt )
3891 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3892 return Window::PreNotify( rNEvt );
3893 else
3894 return PreNotify( rNEvt );
3897 bool Window::CompatNotify( NotifyEvent& rNEvt )
3899 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3900 return Window::EventNotify( rNEvt );
3901 else
3902 return EventNotify( rNEvt );
3905 void Window::set_id(const OUString& rID)
3907 mpWindowImpl->maID = rID;
3910 const OUString& Window::get_id() const
3912 return mpWindowImpl->maID;
3915 FactoryFunction Window::GetUITestFactory() const
3917 return WindowUIObject::create;
3920 } /* namespace vcl */
3922 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */