bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / window / window.cxx
blob19e2e105a1685acc3ed6b6af2b7008fb2ef9b29f
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 <vcl/salgtype.hxx>
25 #include <vcl/event.hxx>
26 #include <vcl/help.hxx>
27 #include <vcl/cursor.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/vclevent.hxx>
30 #include <vcl/window.hxx>
31 #include <vcl/syswin.hxx>
32 #include <vcl/dockwin.hxx>
33 #include <vcl/wall.hxx>
34 #include <vcl/fixed.hxx>
35 #include <vcl/taskpanelist.hxx>
36 #include <vcl/toolkit/unowrap.hxx>
37 #include <vcl/lazydelete.hxx>
38 #include <vcl/virdev.hxx>
39 #include <vcl/settings.hxx>
40 #include <vcl/sysdata.hxx>
41 #include <vcl/ptrstyle.hxx>
42 #include <vcl/IDialogRenderable.hxx>
44 #include <vcl/uitest/uiobject.hxx>
46 #include <salframe.hxx>
47 #include <salobj.hxx>
48 #include <salinst.hxx>
49 #include <salgdi.hxx>
50 #include <svdata.hxx>
51 #include <window.h>
52 #include <toolbox.h>
53 #include <outdev.h>
54 #include <brdwin.hxx>
55 #include <helpwin.hxx>
57 #include <com/sun/star/accessibility/AccessibleRelation.hpp>
58 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
59 #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
60 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
61 #include <com/sun/star/rendering/CanvasFactory.hpp>
62 #include <com/sun/star/rendering/XSpriteCanvas.hpp>
63 #include <comphelper/lok.hxx>
64 #include <comphelper/processfactory.hxx>
65 #include <unotools/configmgr.hxx>
66 #include <osl/diagnose.h>
67 #include <tools/debug.hxx>
68 #include <boost/property_tree/ptree.hpp>
70 #include <cassert>
71 #include <typeinfo>
73 #ifdef _WIN32 // see #140456#
74 #include <win/salframe.h>
75 #endif
78 using namespace ::com::sun::star::uno;
79 using namespace ::com::sun::star::lang;
80 using namespace ::com::sun::star::datatransfer::clipboard;
81 using namespace ::com::sun::star::datatransfer::dnd;
83 namespace vcl {
85 Window::Window( WindowType nType )
86 : OutputDevice(OUTDEV_WINDOW)
87 , mpWindowImpl(new WindowImpl( nType ))
89 // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
90 mbEnableRTL = AllSettings::GetLayoutRTL();
93 Window::Window( vcl::Window* pParent, WinBits nStyle )
94 : OutputDevice(OUTDEV_WINDOW)
95 , mpWindowImpl(new WindowImpl( WindowType::WINDOW ))
97 // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
98 mbEnableRTL = AllSettings::GetLayoutRTL();
100 ImplInit( pParent, nStyle, nullptr );
103 #if OSL_DEBUG_LEVEL > 0
104 namespace
106 OString lcl_createWindowInfo(const vcl::Window* pWindow)
108 // skip border windows, they do not carry information that
109 // would help with diagnosing the problem
110 const vcl::Window* pTempWin( pWindow );
111 while ( pTempWin && pTempWin->GetType() == WindowType::BORDERWINDOW ) {
112 pTempWin = pTempWin->GetWindow( GetWindowType::FirstChild );
114 // check if pTempWin is not null, otherwise use the
115 // original address
116 if ( pTempWin ) {
117 pWindow = pTempWin;
120 OStringBuffer aErrorString;
121 aErrorString.append(' ');
122 aErrorString.append(typeid( *pWindow ).name());
123 aErrorString.append("(");
124 aErrorString.append(
125 OUStringToOString(
126 pWindow->GetText(),
127 RTL_TEXTENCODING_UTF8
130 aErrorString.append(")");
131 return aErrorString.makeStringAndClear();
134 #endif
136 bool Window::IsDisposed() const
138 return !mpWindowImpl;
141 void Window::dispose()
143 assert( mpWindowImpl );
144 assert( !mpWindowImpl->mbInDispose ); // should only be called from disposeOnce()
145 assert( (!mpWindowImpl->mpParent ||
146 !mpWindowImpl->mpParent->IsDisposed()) &&
147 "vcl::Window child should have its parent disposed first" );
149 // remove Key and Mouse events issued by Application::PostKey/MouseEvent
150 Application::RemoveMouseAndKeyEvents( this );
152 // Dispose of the canvas implementation (which, currently, has an
153 // own wrapper window as a child to this one.
154 Reference< css::rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
155 if( xCanvas.is() )
157 Reference < XComponent > xCanvasComponent( xCanvas, UNO_QUERY );
158 if( xCanvasComponent.is() )
159 xCanvasComponent->dispose();
162 mpWindowImpl->mbInDispose = true;
164 CallEventListeners( VclEventId::ObjectDying );
166 // do not send child events for frames that were registered as native frames
167 if( !ImplIsAccessibleNativeFrame() && mpWindowImpl->mbReallyVisible )
168 if ( ImplIsAccessibleCandidate() && GetAccessibleParentWindow() )
169 GetAccessibleParentWindow()->CallEventListeners( VclEventId::WindowChildDestroyed, this );
171 // remove associated data structures from dockingmanager
172 ImplGetDockingManager()->RemoveWindow( this );
174 // remove ownerdraw decorated windows from list in the top-most frame window
175 if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
177 ::std::vector< VclPtr<vcl::Window> >& rList = ImplGetOwnerDrawList();
178 auto p = ::std::find( rList.begin(), rList.end(), VclPtr<vcl::Window>(this) );
179 if( p != rList.end() )
180 rList.erase( p );
183 // shutdown drag and drop
184 Reference < XComponent > xDnDComponent( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY );
186 if( xDnDComponent.is() )
187 xDnDComponent->dispose();
189 if( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
193 // deregister drop target listener
194 if( mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
196 Reference< XDragGestureRecognizer > xDragGestureRecognizer(mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
197 if( xDragGestureRecognizer.is() )
199 xDragGestureRecognizer->removeDragGestureListener(
200 Reference< XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY));
203 mpWindowImpl->mpFrameData->mxDropTarget->removeDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
204 mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
207 // shutdown drag and drop for this frame window
208 Reference< XComponent > xComponent( mpWindowImpl->mpFrameData->mxDropTarget, UNO_QUERY );
210 // DNDEventDispatcher does not hold a reference of the DropTarget,
211 // so it's ok if it does not support XComponent
212 if( xComponent.is() )
213 xComponent->dispose();
215 catch (const Exception&)
217 // can be safely ignored here.
221 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper( false );
222 if ( pWrapper )
223 pWrapper->WindowDestroyed( this );
225 // MT: Must be called after WindowDestroyed!
226 // Otherwise, if the accessible is a VCLXWindow, it will try to destroy this window again!
227 // But accessibility implementations from applications need this dispose.
228 if ( mpWindowImpl->mxAccessible.is() )
230 Reference< XComponent> xC( mpWindowImpl->mxAccessible, UNO_QUERY );
231 if ( xC.is() )
232 xC->dispose();
235 ImplSVData* pSVData = ImplGetSVData();
237 if ( pSVData->maHelpData.mpHelpWin && (pSVData->maHelpData.mpHelpWin->GetParent() == this) )
238 ImplDestroyHelpWindow( true );
240 SAL_WARN_IF( pSVData->maWinData.mpTrackWin.get() == this, "vcl.window",
241 "Window::~Window(): Window is in TrackingMode" );
242 SAL_WARN_IF(IsMouseCaptured(), "vcl.window",
243 "Window::~Window(): Window has the mouse captured");
245 // due to old compatibility
246 if ( pSVData->maWinData.mpTrackWin == this )
247 EndTracking();
248 if (IsMouseCaptured())
249 ReleaseMouse();
251 #if OSL_DEBUG_LEVEL > 0
252 if ( true ) // always perform these tests in debug builds
254 OStringBuffer aErrorStr;
255 bool bError = false;
256 vcl::Window* pTempWin;
258 if ( mpWindowImpl->mpFirstChild )
260 OStringBuffer aTempStr("Window (");
261 aTempStr.append(lcl_createWindowInfo(this));
262 aTempStr.append(") with live children destroyed: ");
263 pTempWin = mpWindowImpl->mpFirstChild;
264 while ( pTempWin )
266 aTempStr.append(lcl_createWindowInfo(pTempWin));
267 pTempWin = pTempWin->mpWindowImpl->mpNext;
269 OSL_FAIL( aTempStr.getStr() );
270 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
273 if (mpWindowImpl->mpFrameData != nullptr)
275 pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap;
276 while ( pTempWin )
278 if ( ImplIsRealParentPath( pTempWin ) )
280 bError = true;
281 aErrorStr.append(lcl_createWindowInfo(pTempWin));
283 pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
285 if ( bError )
287 OStringBuffer aTempStr;
288 aTempStr.append("Window (");
289 aTempStr.append(lcl_createWindowInfo(this));
290 aTempStr.append(") with live SystemWindows destroyed: ");
291 aTempStr.append(aErrorStr.toString());
292 OSL_FAIL(aTempStr.getStr());
293 // abort in debug builds, must be fixed!
294 Application::Abort(OStringToOUString(
295 aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
299 bError = false;
300 pTempWin = pSVData->maWinData.mpFirstFrame;
301 while ( pTempWin )
303 if ( ImplIsRealParentPath( pTempWin ) )
305 bError = true;
306 aErrorStr.append(lcl_createWindowInfo(pTempWin));
308 pTempWin = pTempWin->mpWindowImpl->mpFrameData->mpNextFrame;
310 if ( bError )
312 OStringBuffer aTempStr( "Window (" );
313 aTempStr.append(lcl_createWindowInfo(this));
314 aTempStr.append(") with live SystemWindows destroyed: ");
315 aTempStr.append(aErrorStr.toString());
316 OSL_FAIL( aTempStr.getStr() );
317 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
320 if ( mpWindowImpl->mpFirstOverlap )
322 OStringBuffer aTempStr("Window (");
323 aTempStr.append(lcl_createWindowInfo(this));
324 aTempStr.append(") with live SystemWindows destroyed: ");
325 pTempWin = mpWindowImpl->mpFirstOverlap;
326 while ( pTempWin )
328 aTempStr.append(lcl_createWindowInfo(pTempWin));
329 pTempWin = pTempWin->mpWindowImpl->mpNext;
331 OSL_FAIL( aTempStr.getStr() );
332 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
335 vcl::Window* pMyParent = GetParent();
336 SystemWindow* pMySysWin = nullptr;
338 while ( pMyParent )
340 if ( pMyParent->IsSystemWindow() )
342 pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
344 pMyParent = pMyParent->GetParent();
346 if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
348 OStringBuffer aTempStr("Window (");
349 aTempStr.append(lcl_createWindowInfo(this));
350 aTempStr.append(") still in TaskPanelList!");
351 OSL_FAIL( aTempStr.getStr() );
352 Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
355 #endif
357 if( mpWindowImpl->mbIsInTaskPaneList )
359 vcl::Window* pMyParent = GetParent();
360 SystemWindow* pMySysWin = nullptr;
362 while ( pMyParent )
364 if ( pMyParent->IsSystemWindow() )
366 pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
368 pMyParent = pMyParent->GetParent();
370 if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
372 pMySysWin->GetTaskPaneList()->RemoveWindow( this );
374 else
376 SAL_WARN( "vcl", "Window (" << GetText() << ") not found in TaskPanelList");
380 // remove from size-group if necessary
381 remove_from_all_size_groups();
383 // clear mnemonic labels
384 std::vector<VclPtr<FixedText> > aMnemonicLabels(list_mnemonic_labels());
385 for (auto const& mnemonicLabel : aMnemonicLabels)
387 remove_mnemonic_label(mnemonicLabel);
390 // hide window in order to trigger the Paint-Handling
391 Hide();
393 // EndExtTextInputMode
394 if ( pSVData->maWinData.mpExtTextInputWin == this )
396 EndExtTextInput();
397 if ( pSVData->maWinData.mpExtTextInputWin == this )
398 pSVData->maWinData.mpExtTextInputWin = nullptr;
401 // check if the focus window is our child
402 bool bHasFocussedChild = false;
403 if( pSVData->maWinData.mpFocusWin && ImplIsRealParentPath( pSVData->maWinData.mpFocusWin ) )
405 // #122232#, this must not happen and is an application bug ! but we try some cleanup to hopefully avoid crashes, see below
406 bHasFocussedChild = true;
407 #if OSL_DEBUG_LEVEL > 0
408 OUString aTempStr = "Window (" + GetText() +
409 ") with focused child window destroyed ! THIS WILL LEAD TO CRASHES AND MUST BE FIXED !";
410 SAL_WARN( "vcl", aTempStr );
411 Application::Abort(aTempStr); // abort in debug build version, this must be fixed!
412 #endif
415 // if we get focus pass focus to another window
416 vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow();
417 if ( pSVData->maWinData.mpFocusWin == this
418 || bHasFocussedChild ) // #122232#, see above, try some cleanup
420 if ( mpWindowImpl->mbFrame )
422 pSVData->maWinData.mpFocusWin = nullptr;
423 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
425 else
427 vcl::Window* pParent = GetParent();
428 vcl::Window* pBorderWindow = mpWindowImpl->mpBorderWindow;
429 // when windows overlap, give focus to the parent
430 // of the next FrameWindow
431 if ( pBorderWindow )
433 if ( pBorderWindow->ImplIsOverlapWindow() )
434 pParent = pBorderWindow->mpWindowImpl->mpOverlapWindow;
436 else if ( ImplIsOverlapWindow() )
437 pParent = mpWindowImpl->mpOverlapWindow;
439 if ( pParent && pParent->IsEnabled() && pParent->IsInputEnabled() && ! pParent->IsInModalMode() )
440 pParent->GrabFocus();
441 else
442 mpWindowImpl->mpFrameWindow->GrabFocus();
444 // If the focus was set back to 'this' set it to nothing
445 if ( pSVData->maWinData.mpFocusWin == this )
447 pSVData->maWinData.mpFocusWin = nullptr;
448 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
453 if ( pOverlapWindow != nullptr &&
454 pOverlapWindow->mpWindowImpl->mpLastFocusWindow == this )
455 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
457 // reset hint for DefModalDialogParent
458 if( pSVData->maWinData.mpActiveApplicationFrame == this )
459 pSVData->maWinData.mpActiveApplicationFrame = nullptr;
461 // reset hint of what was the last wheeled window
462 if( pSVData->maWinData.mpLastWheelWindow == this )
463 pSVData->maWinData.mpLastWheelWindow = nullptr;
465 // reset marked windows
466 if ( mpWindowImpl->mpFrameData != nullptr )
468 if ( mpWindowImpl->mpFrameData->mpFocusWin == this )
469 mpWindowImpl->mpFrameData->mpFocusWin = nullptr;
470 if ( mpWindowImpl->mpFrameData->mpMouseMoveWin == this )
471 mpWindowImpl->mpFrameData->mpMouseMoveWin = nullptr;
472 if ( mpWindowImpl->mpFrameData->mpMouseDownWin == this )
473 mpWindowImpl->mpFrameData->mpMouseDownWin = nullptr;
476 // reset Deactivate-Window
477 if ( pSVData->maWinData.mpLastDeacWin == this )
478 pSVData->maWinData.mpLastDeacWin = nullptr;
480 if ( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
482 if ( mpWindowImpl->mpFrameData->mnFocusId )
483 Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnFocusId );
484 mpWindowImpl->mpFrameData->mnFocusId = nullptr;
485 if ( mpWindowImpl->mpFrameData->mnMouseMoveId )
486 Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId );
487 mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
490 // release SalGraphics
491 OutputDevice *pOutDev = GetOutDev();
492 pOutDev->ReleaseGraphics();
494 // remove window from the lists
495 ImplRemoveWindow( true );
497 // de-register as "top window child" at our parent, if necessary
498 if ( mpWindowImpl->mbFrame )
500 bool bIsTopWindow = mpWindowImpl->mpWinData && ( mpWindowImpl->mpWinData->mnIsTopWindow == 1 );
501 if ( mpWindowImpl->mpRealParent && bIsTopWindow )
503 ImplWinData* pParentWinData = mpWindowImpl->mpRealParent->ImplGetWinData();
505 auto myPos = ::std::find( pParentWinData->maTopWindowChildren.begin(),
506 pParentWinData->maTopWindowChildren.end(), VclPtr<vcl::Window>(this) );
507 SAL_WARN_IF( myPos == pParentWinData->maTopWindowChildren.end(), "vcl.window", "Window::~Window: inconsistency in top window chain!" );
508 if ( myPos != pParentWinData->maTopWindowChildren.end() )
509 pParentWinData->maTopWindowChildren.erase( myPos );
513 delete mpWindowImpl->mpWinData;
514 mpWindowImpl->mpWinData = nullptr;
516 // remove BorderWindow or Frame window data
517 mpWindowImpl->mpBorderWindow.disposeAndClear();
518 if ( mpWindowImpl->mbFrame )
520 if ( pSVData->maWinData.mpFirstFrame == this )
521 pSVData->maWinData.mpFirstFrame = mpWindowImpl->mpFrameData->mpNextFrame;
522 else
524 sal_Int32 nWindows = 0;
525 vcl::Window* pSysWin = pSVData->maWinData.mpFirstFrame;
526 while ( pSysWin && pSysWin->mpWindowImpl->mpFrameData->mpNextFrame.get() != this )
528 pSysWin = pSysWin->mpWindowImpl->mpFrameData->mpNextFrame;
529 nWindows++;
532 if ( pSysWin )
534 assert (mpWindowImpl->mpFrameData->mpNextFrame.get() != pSysWin);
535 pSysWin->mpWindowImpl->mpFrameData->mpNextFrame = mpWindowImpl->mpFrameData->mpNextFrame;
537 else // if it is not in the list, we can't remove it.
538 SAL_WARN("vcl.window", "Window " << this << " marked as frame window, "
539 "is missing from list of " << nWindows << " frames");
541 if (mpWindowImpl->mpFrame) // otherwise exception during init
543 mpWindowImpl->mpFrame->SetCallback( nullptr, nullptr );
544 pSVData->mpDefInst->DestroyFrame( mpWindowImpl->mpFrame );
546 assert (mpWindowImpl->mpFrameData->mnFocusId == nullptr);
547 assert (mpWindowImpl->mpFrameData->mnMouseMoveId == nullptr);
549 mpWindowImpl->mpFrameData->mpBuffer.disposeAndClear();
550 delete mpWindowImpl->mpFrameData;
551 mpWindowImpl->mpFrameData = nullptr;
554 // should be the last statements
555 mpWindowImpl.reset();
557 OutputDevice::dispose();
560 Window::~Window()
562 disposeOnce();
565 // We will eventually being removing the inheritance of OutputDevice
566 // from Window. It will be replaced with a transient relationship such
567 // that the OutputDevice is only live for the scope of the Paint method.
568 // In the meantime this can help move us towards a Window use an
569 // OutputDevice, not being one.
571 ::OutputDevice const* Window::GetOutDev() const
573 return this;
576 ::OutputDevice* Window::GetOutDev()
578 return this;
581 Color Window::GetBackgroundColor() const
583 return GetDisplayBackground().GetColor();
586 } /* namespace vcl */
588 WindowImpl::WindowImpl( WindowType nType )
590 maZoom = Fraction( 1, 1 );
591 maWinRegion = vcl::Region(true);
592 maWinClipRegion = vcl::Region(true);
593 mpWinData = nullptr; // Extra Window Data, that we don't need for all windows
594 mpFrameData = nullptr; // Frame Data
595 mpFrame = nullptr; // Pointer to frame window
596 mpSysObj = nullptr;
597 mpFrameWindow = nullptr; // window to top level parent (same as frame window)
598 mpOverlapWindow = nullptr; // first overlap parent
599 mpBorderWindow = nullptr; // Border-Window
600 mpClientWindow = nullptr; // Client-Window of a FrameWindow
601 mpParent = nullptr; // parent (incl. BorderWindow)
602 mpRealParent = nullptr; // real parent (excl. BorderWindow)
603 mpFirstChild = nullptr; // first child window
604 mpLastChild = nullptr; // last child window
605 mpFirstOverlap = nullptr; // first overlap window (only set in overlap windows)
606 mpLastOverlap = nullptr; // last overlap window (only set in overlap windows)
607 mpPrev = nullptr; // prev window
608 mpNext = nullptr; // next window
609 mpNextOverlap = nullptr; // next overlap window of frame
610 mpLastFocusWindow = nullptr; // window for focus restore
611 mpDlgCtrlDownWindow = nullptr; // window for dialog control
612 mnEventListenersIteratingCount = 0;
613 mnChildEventListenersIteratingCount = 0;
614 mpCursor = nullptr; // cursor
615 maPointer = PointerStyle::Arrow;
616 mpVCLXWindow = nullptr;
617 mpAccessibleInfos = nullptr;
618 maControlForeground = COL_TRANSPARENT; // no foreground set
619 maControlBackground = COL_TRANSPARENT; // no background set
620 mnLeftBorder = 0; // left border
621 mnTopBorder = 0; // top border
622 mnRightBorder = 0; // right border
623 mnBottomBorder = 0; // bottom border
624 mnWidthRequest = -1; // width request
625 mnHeightRequest = -1; // height request
626 mnOptimalWidthCache = -1; // optimal width cache
627 mnOptimalHeightCache = -1; // optimal height cache
628 mnX = 0; // X-Position to Parent
629 mnY = 0; // Y-Position to Parent
630 mnAbsScreenX = 0; // absolute X-position on screen, used for RTL window positioning
631 mpChildClipRegion = nullptr; // Child-Clip-Region when ClipChildren
632 mpPaintRegion = nullptr; // Paint-ClipRegion
633 mnStyle = 0; // style (init in ImplInitWindow)
634 mnPrevStyle = 0; // prevstyle (set in SetStyle)
635 mnExtendedStyle = WindowExtendedStyle::NONE; // extended style (init in ImplInitWindow)
636 mnType = nType; // type
637 mnGetFocusFlags = GetFocusFlags::NONE; // Flags for GetFocus()-Call
638 mnWaitCount = 0; // Wait-Count (>1 == "wait" mouse pointer)
639 mnPaintFlags = ImplPaintFlags::NONE; // Flags for ImplCallPaint
640 mnParentClipMode = ParentClipMode::NONE; // Flags for Parent-ClipChildren-Mode
641 mnActivateMode = ActivateModeFlags::NONE; // Will be converted in System/Overlap-Windows
642 mnDlgCtrlFlags = DialogControlFlags::NONE; // DialogControl-Flags
643 meAlwaysInputMode = AlwaysInputNone; // neither AlwaysEnableInput nor AlwaysDisableInput called
644 meHalign = VclAlign::Fill;
645 meValign = VclAlign::Fill;
646 mePackType = VclPackType::Start;
647 mnPadding = 0;
648 mnGridHeight = 1;
649 mnGridLeftAttach = -1;
650 mnGridTopAttach = -1;
651 mnGridWidth = 1;
652 mnBorderWidth = 0;
653 mnMarginLeft = 0;
654 mnMarginRight = 0;
655 mnMarginTop = 0;
656 mnMarginBottom = 0;
657 mbFrame = false; // true: Window is a frame window
658 mbBorderWin = false; // true: Window is a border window
659 mbOverlapWin = false; // true: Window is an overlap window
660 mbSysWin = false; // true: SystemWindow is the base class
661 mbDialog = false; // true: Dialog is the base class
662 mbDockWin = false; // true: DockingWindow is the base class
663 mbFloatWin = false; // true: FloatingWindow is the base class
664 mbPushButton = false; // true: PushButton is the base class
665 mbToolBox = false; // true: ToolBox is the base class
666 mbMenuFloatingWindow = false; // true: MenuFloatingWindow is the base class
667 mbToolbarFloatingWindow = false; // true: ImplPopupFloatWin is the base class, used for subtoolbars
668 mbSplitter = false; // true: Splitter is the base class
669 mbVisible = false; // true: Show( true ) called
670 mbOverlapVisible = false; // true: Hide called for visible window from ImplHideAllOverlapWindow()
671 mbDisabled = false; // true: Enable( false ) called
672 mbInputDisabled = false; // true: EnableInput( false ) called
673 mbNoUpdate = false; // true: SetUpdateMode( false ) called
674 mbNoParentUpdate = false; // true: SetParentUpdateMode( false ) called
675 mbActive = false; // true: Window Active
676 mbReallyVisible = false; // true: this and all parents to an overlapped window are visible
677 mbReallyShown = false; // true: this and all parents to an overlapped window are shown
678 mbInInitShow = false; // true: we are in InitShow
679 mbChildPtrOverwrite = false; // true: PointerStyle overwrites Child-Pointer
680 mbNoPtrVisible = false; // true: ShowPointer( false ) called
681 mbPaintFrame = false; // true: Paint is visible, but not painted
682 mbInPaint = false; // true: Inside PaintHdl
683 mbMouseButtonDown = false; // true: BaseMouseButtonDown called
684 mbMouseButtonUp = false; // true: BaseMouseButtonUp called
685 mbKeyInput = false; // true: BaseKeyInput called
686 mbKeyUp = false; // true: BaseKeyUp called
687 mbCommand = false; // true: BaseCommand called
688 mbDefPos = true; // true: Position is not Set
689 mbDefSize = true; // true: Size is not Set
690 mbCallMove = true; // true: Move must be called by Show
691 mbCallResize = true; // true: Resize must be called by Show
692 mbWaitSystemResize = true; // true: Wait for System-Resize
693 mbInitWinClipRegion = true; // true: Calc Window Clip Region
694 mbInitChildRegion = false; // true: InitChildClipRegion
695 mbWinRegion = false; // true: Window Region
696 mbClipChildren = false; // true: Child-window should be clipped
697 mbClipSiblings = false; // true: Adjacent Child-window should be clipped
698 mbChildTransparent = false; // true: Child-windows are allowed to switch to transparent (incl. Parent-CLIPCHILDREN)
699 mbPaintTransparent = false; // true: Paints should be executed on the Parent
700 mbMouseTransparent = false; // true: Window is transparent for Mouse
701 mbDlgCtrlStart = false; // true: From here on own Dialog-Control
702 mbFocusVisible = false; // true: Focus Visible
703 mbUseNativeFocus = false;
704 mbNativeFocusVisible = false; // true: native Focus Visible
705 mbInShowFocus = false; // prevent recursion
706 mbInHideFocus = false; // prevent recursion
707 mbTrackVisible = false; // true: Tracking Visible
708 mbControlForeground = false; // true: Foreground-Property set
709 mbControlBackground = false; // true: Background-Property set
710 mbAlwaysOnTop = false; // true: always visible for all others windows
711 mbCompoundControl = false; // true: Composite Control => Listener...
712 mbCompoundControlHasFocus = false; // true: Composite Control has focus somewhere
713 mbPaintDisabled = false; // true: Paint should not be executed
714 mbAllResize = false; // true: Also sent ResizeEvents with 0,0
715 mbInDispose = false; // true: We're still in Window::dispose()
716 mbExtTextInput = false; // true: ExtTextInput-Mode is active
717 mbInFocusHdl = false; // true: Within GetFocus-Handler
718 mbCreatedWithToolkit = false;
719 mbSuppressAccessibilityEvents = false; // true: do not send any accessibility events
720 mbDrawSelectionBackground = false; // true: draws transparent window background to indicate (toolbox) selection
721 mbIsInTaskPaneList = false; // true: window was added to the taskpanelist in the topmost system window
722 mnNativeBackground = ControlPart::NONE; // initialize later, depends on type
723 mbCallHandlersDuringInputDisabled = false; // true: call event handlers even if input is disabled
724 mbHelpTextDynamic = false; // true: append help id in HELP_DEBUG case
725 mbFakeFocusSet = false; // true: pretend as if the window has focus.
726 mbHexpand = false;
727 mbVexpand = false;
728 mbExpand = false;
729 mbFill = true;
730 mbSecondary = false;
731 mbNonHomogeneous = false;
732 static bool bDoubleBuffer = getenv("VCL_DOUBLEBUFFERING_FORCE_ENABLE");
733 mbDoubleBufferingRequested = bDoubleBuffer; // when we are not sure, assume it cannot do double-buffering via RenderContext
734 mpLOKNotifier = nullptr;
735 mnLOKWindowId = 0;
736 mbLOKParentNotifier = false;
739 WindowImpl::~WindowImpl()
741 mpChildClipRegion.reset();
742 mpAccessibleInfos.reset();
745 ImplWinData::ImplWinData() :
746 mnCursorExtWidth(0),
747 mbVertical(false),
748 mnCompositionCharRects(0),
749 mnTrackFlags(ShowTrackFlags::NONE),
750 mnIsTopWindow(sal_uInt16(~0)), // not initialized yet, 0/1 will indicate TopWindow (see IsTopWindow())
751 mbMouseOver(false),
752 mbEnableNativeWidget(false)
756 ImplWinData::~ImplWinData()
758 mpCompositionCharRects.reset();
761 ImplFrameData::ImplFrameData( vcl::Window *pWindow )
763 ImplSVData* pSVData = ImplGetSVData();
764 assert (pSVData->maWinData.mpFirstFrame.get() != pWindow);
765 mpNextFrame = pSVData->maWinData.mpFirstFrame;
766 pSVData->maWinData.mpFirstFrame = pWindow;
767 mpFirstOverlap = nullptr;
768 mpFocusWin = nullptr;
769 mpMouseMoveWin = nullptr;
770 mpMouseDownWin = nullptr;
771 mxFontCollection = pSVData->maGDIData.mxScreenFontList;
772 mxFontCache = pSVData->maGDIData.mxScreenFontCache;
773 mnFocusId = nullptr;
774 mnMouseMoveId = nullptr;
775 mnLastMouseX = -1;
776 mnLastMouseY = -1;
777 mnBeforeLastMouseX = -1;
778 mnBeforeLastMouseY = -1;
779 mnFirstMouseX = -1;
780 mnFirstMouseY = -1;
781 mnLastMouseWinX = -1;
782 mnLastMouseWinY = -1;
783 mnModalMode = 0;
784 mnMouseDownTime = 0;
785 mnClickCount = 0;
786 mnFirstMouseCode = 0;
787 mnMouseCode = 0;
788 mnMouseMode = MouseEventModifiers::NONE;
789 mbHasFocus = false;
790 mbInMouseMove = false;
791 mbMouseIn = false;
792 mbStartDragCalled = false;
793 mbNeedSysWindow = false;
794 mbMinimized = false;
795 mbStartFocusState = false;
796 mbInSysObjFocusHdl = false;
797 mbInSysObjToTopHdl = false;
798 mbSysObjFocus = false;
799 maPaintIdle.SetPriority( TaskPriority::REPAINT );
800 maPaintIdle.SetInvokeHandler( LINK( pWindow, vcl::Window, ImplHandlePaintHdl ) );
801 maPaintIdle.SetDebugName( "vcl::Window maPaintIdle" );
802 maResizeIdle.SetPriority( TaskPriority::RESIZE );
803 maResizeIdle.SetInvokeHandler( LINK( pWindow, vcl::Window, ImplHandleResizeTimerHdl ) );
804 maResizeIdle.SetDebugName( "vcl::Window maResizeIdle" );
805 mbInternalDragGestureRecognizer = false;
806 mbInBufferedPaint = false;
807 mnDPIX = 96;
808 mnDPIY = 96;
809 mnTouchPanPosition = -1;
812 namespace vcl {
814 bool Window::AcquireGraphics() const
816 DBG_TESTSOLARMUTEX();
818 if ( mpGraphics )
819 return true;
821 mbInitLineColor = true;
822 mbInitFillColor = true;
823 mbInitFont = true;
824 mbInitTextColor = true;
825 mbInitClipRegion = true;
827 ImplSVData* pSVData = ImplGetSVData();
829 mpGraphics = mpWindowImpl->mpFrame->AcquireGraphics();
830 // try harder if no wingraphics was available directly
831 if ( !mpGraphics )
833 // find another output device in the same frame
834 OutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics;
835 while ( pReleaseOutDev )
837 if ( static_cast<vcl::Window*>(pReleaseOutDev)->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame )
838 break;
839 pReleaseOutDev = pReleaseOutDev->mpPrevGraphics;
842 if ( pReleaseOutDev )
844 // steal the wingraphics from the other outdev
845 mpGraphics = pReleaseOutDev->mpGraphics;
846 pReleaseOutDev->ReleaseGraphics( false );
848 else
850 // if needed retry after releasing least recently used wingraphics
851 while ( !mpGraphics )
853 if ( !pSVData->maGDIData.mpLastWinGraphics )
854 break;
855 pSVData->maGDIData.mpLastWinGraphics->ReleaseGraphics();
856 mpGraphics = mpWindowImpl->mpFrame->AcquireGraphics();
861 if ( mpGraphics )
863 // update global LRU list of wingraphics
864 mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics;
865 pSVData->maGDIData.mpFirstWinGraphics = const_cast<vcl::Window*>(this);
866 if ( mpNextGraphics )
867 mpNextGraphics->mpPrevGraphics = const_cast<vcl::Window*>(this);
868 if ( !pSVData->maGDIData.mpLastWinGraphics )
869 pSVData->maGDIData.mpLastWinGraphics = const_cast<vcl::Window*>(this);
871 mpGraphics->SetXORMode( (RasterOp::Invert == meRasterOp) || (RasterOp::Xor == meRasterOp), RasterOp::Invert == meRasterOp );
872 mpGraphics->setAntiAliasB2DDraw(bool(mnAntialiasing & AntialiasingFlags::EnableB2dDraw));
875 return mpGraphics != nullptr;
878 void Window::ReleaseGraphics( bool bRelease )
880 DBG_TESTSOLARMUTEX();
882 if ( !mpGraphics )
883 return;
885 // release the fonts of the physically released graphics device
886 if( bRelease )
887 ImplReleaseFonts();
889 ImplSVData* pSVData = ImplGetSVData();
891 vcl::Window* pWindow = this;
893 if ( bRelease )
894 pWindow->mpWindowImpl->mpFrame->ReleaseGraphics( mpGraphics );
895 // remove from global LRU list of window graphics
896 if ( mpPrevGraphics )
897 mpPrevGraphics->mpNextGraphics = mpNextGraphics;
898 else
899 pSVData->maGDIData.mpFirstWinGraphics = mpNextGraphics;
900 if ( mpNextGraphics )
901 mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
902 else
903 pSVData->maGDIData.mpLastWinGraphics = mpPrevGraphics;
905 mpGraphics = nullptr;
906 mpPrevGraphics = nullptr;
907 mpNextGraphics = nullptr;
910 static sal_Int32 CountDPIScaleFactor(sal_Int32 nDPI)
912 #ifndef MACOSX
913 // Setting of HiDPI is unfortunately all only a heuristic; and to add
914 // insult to an injury, the system is constantly lying to us about
915 // the DPI and whatnot
916 // eg. fdo#77059 - set the value from which we do consider the
917 // screen HiDPI to greater than 168
918 if (nDPI > 216) // 96 * 2 + 96 / 4
919 return 250;
920 else if (nDPI > 168) // 96 * 2 - 96 / 4
921 return 200;
922 else if (nDPI > 120) // 96 * 1.5 - 96 / 4
923 return 150;
924 #else
925 (void)nDPI;
926 #endif
928 return 100;
931 void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
933 SAL_WARN_IF( !mpWindowImpl->mbFrame && !pParent && GetType() != WindowType::FIXEDIMAGE, "vcl.window",
934 "Window::Window(): pParent == NULL" );
936 ImplSVData* pSVData = ImplGetSVData();
937 vcl::Window* pRealParent = pParent;
939 // inherit 3D look
940 if ( !mpWindowImpl->mbOverlapWin && pParent && (pParent->GetStyle() & WB_3DLOOK) )
941 nStyle |= WB_3DLOOK;
943 // create border window if necessary
944 if ( !mpWindowImpl->mbFrame && !mpWindowImpl->mbBorderWin && !mpWindowImpl->mpBorderWindow
945 && (nStyle & (WB_BORDER | WB_SYSTEMCHILDWINDOW) ) )
947 BorderWindowStyle nBorderTypeStyle = BorderWindowStyle::NONE;
948 if( nStyle & WB_SYSTEMCHILDWINDOW )
950 // handle WB_SYSTEMCHILDWINDOW
951 // these should be analogous to a top level frame; meaning they
952 // should have a border window with style BorderWindowStyle::Frame
953 // which controls their size
954 nBorderTypeStyle |= BorderWindowStyle::Frame;
955 nStyle |= WB_BORDER;
957 VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL), nBorderTypeStyle );
958 static_cast<vcl::Window*>(pBorderWin)->mpWindowImpl->mpClientWindow = this;
959 pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
960 mpWindowImpl->mpBorderWindow = pBorderWin;
961 pParent = mpWindowImpl->mpBorderWindow;
963 else if( !mpWindowImpl->mbFrame && ! pParent )
965 mpWindowImpl->mbOverlapWin = true;
966 mpWindowImpl->mbFrame = true;
969 // insert window in list
970 ImplInsertWindow( pParent );
971 mpWindowImpl->mnStyle = nStyle;
973 if( pParent && ! mpWindowImpl->mbFrame )
974 mbEnableRTL = AllSettings::GetLayoutRTL();
976 // test for frame creation
977 if ( mpWindowImpl->mbFrame )
979 // create frame
980 SalFrameStyleFlags nFrameStyle = SalFrameStyleFlags::NONE;
982 if ( nStyle & WB_MOVEABLE )
983 nFrameStyle |= SalFrameStyleFlags::MOVEABLE;
984 if ( nStyle & WB_SIZEABLE )
985 nFrameStyle |= SalFrameStyleFlags::SIZEABLE;
986 if ( nStyle & WB_CLOSEABLE )
987 nFrameStyle |= SalFrameStyleFlags::CLOSEABLE;
988 if ( nStyle & WB_APP )
989 nFrameStyle |= SalFrameStyleFlags::DEFAULT;
990 // check for undecorated floating window
991 if( // 1. floating windows that are not moveable/sizeable (only closeable allowed)
992 ( !(nFrameStyle & ~SalFrameStyleFlags::CLOSEABLE) &&
993 ( mpWindowImpl->mbFloatWin || ((GetType() == WindowType::BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow) || (nStyle & WB_SYSTEMFLOATWIN) ) ) ||
994 // 2. borderwindows of floaters with ownerdraw decoration
995 ((GetType() == WindowType::BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow && (nStyle & WB_OWNERDRAWDECORATION) ) )
997 nFrameStyle = SalFrameStyleFlags::FLOAT;
998 if( nStyle & WB_OWNERDRAWDECORATION )
999 nFrameStyle |= SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::NOSHADOW;
1001 else if( mpWindowImpl->mbFloatWin )
1002 nFrameStyle |= SalFrameStyleFlags::TOOLWINDOW;
1004 if( nStyle & WB_INTROWIN )
1005 nFrameStyle |= SalFrameStyleFlags::INTRO;
1006 if( nStyle & WB_TOOLTIPWIN )
1007 nFrameStyle |= SalFrameStyleFlags::TOOLTIP;
1009 if( nStyle & WB_NOSHADOW )
1010 nFrameStyle |= SalFrameStyleFlags::NOSHADOW;
1012 if( nStyle & WB_SYSTEMCHILDWINDOW )
1013 nFrameStyle |= SalFrameStyleFlags::SYSTEMCHILD;
1015 switch (mpWindowImpl->mnType)
1017 case WindowType::DIALOG:
1018 case WindowType::TABDIALOG:
1019 case WindowType::MODALDIALOG:
1020 case WindowType::MODELESSDIALOG:
1021 case WindowType::MESSBOX:
1022 case WindowType::INFOBOX:
1023 case WindowType::WARNINGBOX:
1024 case WindowType::ERRORBOX:
1025 case WindowType::QUERYBOX:
1026 nFrameStyle |= SalFrameStyleFlags::DIALOG;
1027 break;
1028 default:
1029 break;
1032 SalFrame* pParentFrame = nullptr;
1033 if ( pParent )
1034 pParentFrame = pParent->mpWindowImpl->mpFrame;
1035 SalFrame* pFrame;
1036 if ( pSystemParentData )
1037 pFrame = pSVData->mpDefInst->CreateChildFrame( pSystemParentData, nFrameStyle | SalFrameStyleFlags::PLUG );
1038 else
1039 pFrame = pSVData->mpDefInst->CreateFrame( pParentFrame, nFrameStyle );
1040 if ( !pFrame )
1042 // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario)
1043 throw RuntimeException(
1044 "Could not create system window!",
1045 Reference< XInterface >() );
1048 pFrame->SetCallback( this, ImplWindowFrameProc );
1050 // set window frame data
1051 mpWindowImpl->mpFrameData = new ImplFrameData( this );
1052 mpWindowImpl->mpFrame = pFrame;
1053 mpWindowImpl->mpFrameWindow = this;
1054 mpWindowImpl->mpOverlapWindow = this;
1056 if (!(nStyle & WB_DEFAULTWIN) && mpWindowImpl->mbDoubleBufferingRequested)
1057 RequestDoubleBuffering(true);
1059 if ( pRealParent && IsTopWindow() )
1061 ImplWinData* pParentWinData = pRealParent->ImplGetWinData();
1062 pParentWinData->maTopWindowChildren.emplace_back(this );
1066 // init data
1067 mpWindowImpl->mpRealParent = pRealParent;
1069 // #99318: make sure fontcache and list is available before call to SetSettings
1070 mxFontCollection = mpWindowImpl->mpFrameData->mxFontCollection;
1071 mxFontCache = mpWindowImpl->mpFrameData->mxFontCache;
1073 if ( mpWindowImpl->mbFrame )
1075 if ( pParent )
1077 mpWindowImpl->mpFrameData->mnDPIX = pParent->mpWindowImpl->mpFrameData->mnDPIX;
1078 mpWindowImpl->mpFrameData->mnDPIY = pParent->mpWindowImpl->mpFrameData->mnDPIY;
1080 else
1082 OutputDevice *pOutDev = GetOutDev();
1083 if ( pOutDev->AcquireGraphics() )
1085 mpGraphics->GetResolution( mpWindowImpl->mpFrameData->mnDPIX, mpWindowImpl->mpFrameData->mnDPIY );
1089 // add ownerdraw decorated frame windows to list in the top-most frame window
1090 // so they can be hidden on lose focus
1091 if( nStyle & WB_OWNERDRAWDECORATION )
1092 ImplGetOwnerDrawList().emplace_back(this );
1094 // delay settings initialization until first "real" frame
1095 // this relies on the IntroWindow not needing any system settings
1096 if ( !pSVData->maAppData.mbSettingsInit &&
1097 ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN))
1100 // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
1101 ImplUpdateGlobalSettings( *pSVData->maAppData.mpSettings );
1102 OutputDevice::SetSettings( *pSVData->maAppData.mpSettings );
1103 pSVData->maAppData.mbSettingsInit = true;
1106 // If we create a Window with default size, query this
1107 // size directly, because we want resize all Controls to
1108 // the correct size before we display the window
1109 if ( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_APP) )
1110 mpWindowImpl->mpFrame->GetClientSize( mnOutWidth, mnOutHeight );
1112 else
1114 if ( pParent )
1116 if ( !ImplIsOverlapWindow() )
1118 mpWindowImpl->mbDisabled = pParent->mpWindowImpl->mbDisabled;
1119 mpWindowImpl->mbInputDisabled = pParent->mpWindowImpl->mbInputDisabled;
1120 mpWindowImpl->meAlwaysInputMode = pParent->mpWindowImpl->meAlwaysInputMode;
1123 if (!utl::ConfigManager::IsFuzzing())
1124 OutputDevice::SetSettings( pParent->GetSettings() );
1129 // setup the scale factor for HiDPI displays
1130 mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
1131 mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
1132 mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
1134 if (!utl::ConfigManager::IsFuzzing())
1136 const StyleSettings& rStyleSettings = mxSettings->GetStyleSettings();
1137 maFont = rStyleSettings.GetAppFont();
1139 if ( nStyle & WB_3DLOOK )
1141 SetTextColor( rStyleSettings.GetButtonTextColor() );
1142 SetBackground( Wallpaper( rStyleSettings.GetFaceColor() ) );
1144 else
1146 SetTextColor( rStyleSettings.GetWindowTextColor() );
1147 SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
1150 else
1152 maFont = GetDefaultFont( DefaultFontType::FIXED, LANGUAGE_ENGLISH_US, GetDefaultFontFlags::NONE );
1155 ImplPointToLogic(*this, maFont);
1157 (void)ImplUpdatePos();
1159 // calculate app font res (except for the Intro Window or the default window)
1160 if ( mpWindowImpl->mbFrame && !pSVData->maGDIData.mnAppFontX && ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN)) )
1161 ImplInitAppFontData( this );
1164 void Window::ImplInitAppFontData( vcl::Window const * pWindow )
1166 ImplSVData* pSVData = ImplGetSVData();
1167 long nTextHeight = pWindow->GetTextHeight();
1168 long nTextWidth = pWindow->approximate_char_width() * 8;
1169 long nSymHeight = nTextHeight*4;
1170 // Make the basis wider if the font is too narrow
1171 // such that the dialog looks symmetrical and does not become too narrow.
1172 // Add some extra space when the dialog has the same width,
1173 // as a little more space is better.
1174 if ( nSymHeight > nTextWidth )
1175 nTextWidth = nSymHeight;
1176 else if ( nSymHeight+5 > nTextWidth )
1177 nTextWidth = nSymHeight+5;
1178 pSVData->maGDIData.mnAppFontX = nTextWidth * 10 / 8;
1179 pSVData->maGDIData.mnAppFontY = nTextHeight * 10;
1181 #ifdef MACOSX
1182 // FIXME: this is currently only on macOS, check with other
1183 // platforms
1184 if( pSVData->maNWFData.mbNoFocusRects )
1186 // try to find out whether there is a large correction
1187 // of control sizes, if yes, make app font scalings larger
1188 // so dialog positioning is not completely off
1189 ImplControlValue aControlValue;
1190 tools::Rectangle aCtrlRegion( Point(), Size( nTextWidth < 10 ? 10 : nTextWidth, nTextHeight < 10 ? 10 : nTextHeight ) );
1191 tools::Rectangle aBoundingRgn( aCtrlRegion );
1192 tools::Rectangle aContentRgn( aCtrlRegion );
1193 if( pWindow->GetNativeControlRegion( ControlType::Editbox, ControlPart::Entire, aCtrlRegion,
1194 ControlState::ENABLED, aControlValue,
1195 aBoundingRgn, aContentRgn ) )
1197 // comment: the magical +6 is for the extra border in bordered
1198 // (which is the standard) edit fields
1199 if( aContentRgn.GetHeight() - nTextHeight > (nTextHeight+4)/4 )
1200 pSVData->maGDIData.mnAppFontY = (aContentRgn.GetHeight()-4) * 10;
1203 #endif
1206 ImplWinData* Window::ImplGetWinData() const
1208 if ( !mpWindowImpl->mpWinData )
1210 static const char* pNoNWF = getenv( "SAL_NO_NWF" );
1212 const_cast<vcl::Window*>(this)->mpWindowImpl->mpWinData = new ImplWinData;
1213 mpWindowImpl->mpWinData->mbEnableNativeWidget = !(pNoNWF && *pNoNWF); // true: try to draw this control with native theme API
1216 return mpWindowImpl->mpWinData;
1220 void Window::CopyDeviceArea( SalTwoRect& aPosAry, bool bWindowInvalidate )
1222 if (aPosAry.mnSrcWidth == 0 || aPosAry.mnSrcHeight == 0 || aPosAry.mnDestWidth == 0 || aPosAry.mnDestHeight == 0)
1223 return;
1225 if (bWindowInvalidate)
1227 const tools::Rectangle aSrcRect(Point(aPosAry.mnSrcX, aPosAry.mnSrcY),
1228 Size(aPosAry.mnSrcWidth, aPosAry.mnSrcHeight));
1230 ImplMoveAllInvalidateRegions(aSrcRect,
1231 aPosAry.mnDestX-aPosAry.mnSrcX,
1232 aPosAry.mnDestY-aPosAry.mnSrcY,
1233 false);
1235 mpGraphics->CopyArea(aPosAry.mnDestX, aPosAry.mnDestY,
1236 aPosAry.mnSrcX, aPosAry.mnSrcY,
1237 aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
1238 this);
1240 return;
1243 OutputDevice::CopyDeviceArea(aPosAry, bWindowInvalidate);
1246 SalGraphics* Window::ImplGetFrameGraphics() const
1248 if ( mpWindowImpl->mpFrameWindow->mpGraphics )
1250 mpWindowImpl->mpFrameWindow->mbInitClipRegion = true;
1252 else
1254 OutputDevice* pFrameWinOutDev = mpWindowImpl->mpFrameWindow;
1255 if ( ! pFrameWinOutDev->AcquireGraphics() )
1257 return nullptr;
1260 mpWindowImpl->mpFrameWindow->mpGraphics->ResetClipRegion();
1261 return mpWindowImpl->mpFrameWindow->mpGraphics;
1264 void Window::ImplSetReallyVisible()
1266 // #i43594# it is possible that INITSHOW was never send, because the visibility state changed between
1267 // ImplCallInitShow() and ImplSetReallyVisible() when called from Show()
1268 // mbReallyShown is a useful indicator
1269 if( !mpWindowImpl->mbReallyShown )
1270 ImplCallInitShow();
1272 bool bBecameReallyVisible = !mpWindowImpl->mbReallyVisible;
1274 mbDevOutput = true;
1275 mpWindowImpl->mbReallyVisible = true;
1276 mpWindowImpl->mbReallyShown = true;
1278 // the SHOW/HIDE events serve as indicators to send child creation/destroy events to the access bridge.
1279 // For this, the data member of the event must not be NULL.
1280 // Previously, we did this in Window::Show, but there some events got lost in certain situations. Now
1281 // we're doing it when the visibility really changes
1282 if( bBecameReallyVisible && ImplIsAccessibleCandidate() )
1283 CallEventListeners( VclEventId::WindowShow, this );
1284 // TODO. It's kind of a hack that we're re-using the VclEventId::WindowShow. Normally, we should
1285 // introduce another event which explicitly triggers the Accessibility implementations.
1287 vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
1288 while ( pWindow )
1290 if ( pWindow->mpWindowImpl->mbVisible )
1291 pWindow->ImplSetReallyVisible();
1292 pWindow = pWindow->mpWindowImpl->mpNext;
1295 pWindow = mpWindowImpl->mpFirstChild;
1296 while ( pWindow )
1298 if ( pWindow->mpWindowImpl->mbVisible )
1299 pWindow->ImplSetReallyVisible();
1300 pWindow = pWindow->mpWindowImpl->mpNext;
1304 void Window::ImplInitResolutionSettings()
1306 // recalculate AppFont-resolution and DPI-resolution
1307 if (mpWindowImpl->mbFrame)
1309 mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
1310 mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
1312 // setup the scale factor for HiDPI displays
1313 mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
1314 const StyleSettings& rStyleSettings = mxSettings->GetStyleSettings();
1315 SetPointFont(*this, rStyleSettings.GetAppFont());
1317 else if ( mpWindowImpl->mpParent )
1319 mnDPIX = mpWindowImpl->mpParent->mnDPIX;
1320 mnDPIY = mpWindowImpl->mpParent->mnDPIY;
1321 mnDPIScalePercentage = mpWindowImpl->mpParent->mnDPIScalePercentage;
1324 // update the recalculated values for logical units
1325 // and also tools belonging to the values
1326 if (IsMapModeEnabled())
1328 MapMode aMapMode = GetMapMode();
1329 SetMapMode();
1330 SetMapMode( aMapMode );
1334 void Window::ImplPointToLogic(vcl::RenderContext const & rRenderContext, vcl::Font& rFont) const
1336 Size aSize = rFont.GetFontSize();
1338 if (aSize.Width())
1340 aSize.setWidth( aSize.Width() * ( mpWindowImpl->mpFrameData->mnDPIX) );
1341 aSize.AdjustWidth(72 / 2 );
1342 aSize.setWidth( aSize.Width() / 72 );
1344 aSize.setHeight( aSize.Height() * ( mpWindowImpl->mpFrameData->mnDPIY) );
1345 aSize.AdjustHeight(72/2 );
1346 aSize.setHeight( aSize.Height() / 72 );
1348 if (rRenderContext.IsMapModeEnabled())
1349 aSize = rRenderContext.PixelToLogic(aSize);
1351 rFont.SetFontSize(aSize);
1354 void Window::ImplLogicToPoint(vcl::RenderContext const & rRenderContext, vcl::Font& rFont) const
1356 Size aSize = rFont.GetFontSize();
1358 if (rRenderContext.IsMapModeEnabled())
1359 aSize = rRenderContext.LogicToPixel(aSize);
1361 if (aSize.Width())
1363 aSize.setWidth( aSize.Width() * 72 );
1364 aSize.AdjustWidth(mpWindowImpl->mpFrameData->mnDPIX / 2 );
1365 aSize.setWidth( aSize.Width() / ( mpWindowImpl->mpFrameData->mnDPIX) );
1367 aSize.setHeight( aSize.Height() * 72 );
1368 aSize.AdjustHeight(mpWindowImpl->mpFrameData->mnDPIY / 2 );
1369 aSize.setHeight( aSize.Height() / ( mpWindowImpl->mpFrameData->mnDPIY) );
1371 rFont.SetFontSize(aSize);
1374 bool Window::ImplUpdatePos()
1376 bool bSysChild = false;
1378 if ( ImplIsOverlapWindow() )
1380 mnOutOffX = mpWindowImpl->mnX;
1381 mnOutOffY = mpWindowImpl->mnY;
1383 else
1385 vcl::Window* pParent = ImplGetParent();
1387 mnOutOffX = mpWindowImpl->mnX + pParent->mnOutOffX;
1388 mnOutOffY = mpWindowImpl->mnY + pParent->mnOutOffY;
1391 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
1392 while ( pChild )
1394 if ( pChild->ImplUpdatePos() )
1395 bSysChild = true;
1396 pChild = pChild->mpWindowImpl->mpNext;
1399 if ( mpWindowImpl->mpSysObj )
1400 bSysChild = true;
1402 return bSysChild;
1405 void Window::ImplUpdateSysObjPos()
1407 if ( mpWindowImpl->mpSysObj )
1408 mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
1410 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
1411 while ( pChild )
1413 pChild->ImplUpdateSysObjPos();
1414 pChild = pChild->mpWindowImpl->mpNext;
1418 void Window::ImplPosSizeWindow( long nX, long nY,
1419 long nWidth, long nHeight, PosSizeFlags nFlags )
1421 bool bNewPos = false;
1422 bool bNewSize = false;
1423 bool bCopyBits = false;
1424 long nOldOutOffX = mnOutOffX;
1425 long nOldOutOffY = mnOutOffY;
1426 long nOldOutWidth = mnOutWidth;
1427 long nOldOutHeight = mnOutHeight;
1428 std::unique_ptr<vcl::Region> pOverlapRegion;
1429 std::unique_ptr<vcl::Region> pOldRegion;
1431 if ( IsReallyVisible() )
1433 tools::Rectangle aOldWinRect( Point( nOldOutOffX, nOldOutOffY ),
1434 Size( nOldOutWidth, nOldOutHeight ) );
1435 pOldRegion.reset( new vcl::Region( aOldWinRect ) );
1436 if ( mpWindowImpl->mbWinRegion )
1437 pOldRegion->Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1439 if ( mnOutWidth && mnOutHeight && !mpWindowImpl->mbPaintTransparent &&
1440 !mpWindowImpl->mbInitWinClipRegion && !mpWindowImpl->maWinClipRegion.IsEmpty() &&
1441 !HasPaintEvent() )
1442 bCopyBits = true;
1445 bool bnXRecycled = false; // avoid duplicate mirroring in RTL case
1446 if ( nFlags & PosSizeFlags::Width )
1448 if(!( nFlags & PosSizeFlags::X ))
1450 nX = mpWindowImpl->mnX;
1451 nFlags |= PosSizeFlags::X;
1452 bnXRecycled = true; // we're using a mnX which was already mirrored in RTL case
1455 if ( nWidth < 0 )
1456 nWidth = 0;
1457 if ( nWidth != mnOutWidth )
1459 mnOutWidth = nWidth;
1460 bNewSize = true;
1461 bCopyBits = false;
1464 if ( nFlags & PosSizeFlags::Height )
1466 if ( nHeight < 0 )
1467 nHeight = 0;
1468 if ( nHeight != mnOutHeight )
1470 mnOutHeight = nHeight;
1471 bNewSize = true;
1472 bCopyBits = false;
1476 if ( nFlags & PosSizeFlags::X )
1478 long nOrgX = nX;
1479 Point aPtDev( Point( nX+mnOutOffX, 0 ) );
1480 OutputDevice *pOutDev = GetOutDev();
1481 if( pOutDev->HasMirroredGraphics() )
1483 aPtDev.setX( mpGraphics->mirror2( aPtDev.X(), this ) );
1485 // #106948# always mirror our pos if our parent is not mirroring, even
1486 // if we are also not mirroring
1487 // RTL: check if parent is in different coordinates
1488 if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
1490 nX = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - nX;
1492 /* #i99166# An LTR window in RTL UI that gets sized only would be
1493 expected to not moved its upper left point
1495 if( bnXRecycled )
1497 if( ImplIsAntiparallel() )
1499 aPtDev.setX( mpWindowImpl->mnAbsScreenX );
1500 nOrgX = mpWindowImpl->maPos.X();
1504 else if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
1506 // mirrored window in LTR UI
1507 nX = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - nX;
1510 // check maPos as well, as it could have been changed for client windows (ImplCallMove())
1511 if ( mpWindowImpl->mnAbsScreenX != aPtDev.X() || nX != mpWindowImpl->mnX || nOrgX != mpWindowImpl->maPos.X() )
1513 if ( bCopyBits && !pOverlapRegion )
1515 pOverlapRegion.reset( new vcl::Region() );
1516 ImplCalcOverlapRegion( tools::Rectangle( Point( mnOutOffX, mnOutOffY ),
1517 Size( mnOutWidth, mnOutHeight ) ),
1518 *pOverlapRegion, false, true );
1520 mpWindowImpl->mnX = nX;
1521 mpWindowImpl->maPos.setX( nOrgX );
1522 mpWindowImpl->mnAbsScreenX = aPtDev.X();
1523 bNewPos = true;
1526 if ( nFlags & PosSizeFlags::Y )
1528 // check maPos as well, as it could have been changed for client windows (ImplCallMove())
1529 if ( nY != mpWindowImpl->mnY || nY != mpWindowImpl->maPos.Y() )
1531 if ( bCopyBits && !pOverlapRegion )
1533 pOverlapRegion.reset( new vcl::Region() );
1534 ImplCalcOverlapRegion( tools::Rectangle( Point( mnOutOffX, mnOutOffY ),
1535 Size( mnOutWidth, mnOutHeight ) ),
1536 *pOverlapRegion, false, true );
1538 mpWindowImpl->mnY = nY;
1539 mpWindowImpl->maPos.setY( nY );
1540 bNewPos = true;
1544 if ( bNewPos || bNewSize )
1546 bool bUpdateSysObjPos = false;
1547 if ( bNewPos )
1548 bUpdateSysObjPos = ImplUpdatePos();
1550 // the borderwindow always specifies the position for its client window
1551 if ( mpWindowImpl->mpBorderWindow )
1552 mpWindowImpl->maPos = mpWindowImpl->mpBorderWindow->mpWindowImpl->maPos;
1554 if ( mpWindowImpl->mpClientWindow )
1556 mpWindowImpl->mpClientWindow->ImplPosSizeWindow( mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder,
1557 mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder,
1558 mnOutWidth-mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnRightBorder,
1559 mnOutHeight-mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnBottomBorder,
1560 PosSizeFlags::X | PosSizeFlags::Y |
1561 PosSizeFlags::Width | PosSizeFlags::Height );
1562 // If we have a client window, then this is the position
1563 // of the Application's floating windows
1564 mpWindowImpl->mpClientWindow->mpWindowImpl->maPos = mpWindowImpl->maPos;
1565 if ( bNewPos )
1567 if ( mpWindowImpl->mpClientWindow->IsVisible() )
1569 mpWindowImpl->mpClientWindow->ImplCallMove();
1571 else
1573 mpWindowImpl->mpClientWindow->mpWindowImpl->mbCallMove = true;
1578 // Move()/Resize() will be called only for Show(), such that
1579 // at least one is called before Show()
1580 if ( IsVisible() )
1582 if ( bNewPos )
1584 ImplCallMove();
1586 if ( bNewSize )
1588 ImplCallResize();
1591 else
1593 if ( bNewPos )
1594 mpWindowImpl->mbCallMove = true;
1595 if ( bNewSize )
1596 mpWindowImpl->mbCallResize = true;
1599 bool bUpdateSysObjClip = false;
1600 if ( IsReallyVisible() )
1602 if ( bNewPos || bNewSize )
1604 // set Clip-Flag
1605 bUpdateSysObjClip = !ImplSetClipFlag( true );
1608 // invalidate window content ?
1609 if ( bNewPos || (mnOutWidth > nOldOutWidth) || (mnOutHeight > nOldOutHeight) )
1611 if ( bNewPos )
1613 bool bInvalidate = false;
1614 bool bParentPaint = true;
1615 if ( !ImplIsOverlapWindow() )
1616 bParentPaint = mpWindowImpl->mpParent->IsPaintEnabled();
1617 if ( bCopyBits && bParentPaint && !HasPaintEvent() )
1619 Point aPoint( mnOutOffX, mnOutOffY );
1620 vcl::Region aRegion( tools::Rectangle( aPoint,
1621 Size( mnOutWidth, mnOutHeight ) ) );
1622 if ( mpWindowImpl->mbWinRegion )
1623 aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1624 ImplClipBoundaries( aRegion, false, true );
1625 if ( !pOverlapRegion->IsEmpty() )
1627 pOverlapRegion->Move( mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY );
1628 aRegion.Exclude( *pOverlapRegion );
1630 if ( !aRegion.IsEmpty() )
1632 // adapt Paint areas
1633 ImplMoveAllInvalidateRegions( tools::Rectangle( Point( nOldOutOffX, nOldOutOffY ),
1634 Size( nOldOutWidth, nOldOutHeight ) ),
1635 mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY,
1636 true );
1637 SalGraphics* pGraphics = ImplGetFrameGraphics();
1638 if ( pGraphics )
1641 OutputDevice *pOutDev = GetOutDev();
1642 const bool bSelectClipRegion = pOutDev->SelectClipRegion( aRegion, pGraphics );
1643 if ( bSelectClipRegion )
1645 pGraphics->CopyArea( mnOutOffX, mnOutOffY,
1646 nOldOutOffX, nOldOutOffY,
1647 nOldOutWidth, nOldOutHeight,
1648 this );
1650 else
1651 bInvalidate = true;
1653 else
1654 bInvalidate = true;
1655 if ( !bInvalidate )
1657 if ( !pOverlapRegion->IsEmpty() )
1658 ImplInvalidateFrameRegion( pOverlapRegion.get(), InvalidateFlags::Children );
1661 else
1662 bInvalidate = true;
1664 else
1665 bInvalidate = true;
1666 if ( bInvalidate )
1667 ImplInvalidateFrameRegion( nullptr, InvalidateFlags::Children );
1669 else
1671 Point aPoint( mnOutOffX, mnOutOffY );
1672 vcl::Region aRegion( tools::Rectangle( aPoint,
1673 Size( mnOutWidth, mnOutHeight ) ) );
1674 aRegion.Exclude( *pOldRegion );
1675 if ( mpWindowImpl->mbWinRegion )
1676 aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
1677 ImplClipBoundaries( aRegion, false, true );
1678 if ( !aRegion.IsEmpty() )
1679 ImplInvalidateFrameRegion( &aRegion, InvalidateFlags::Children );
1683 // invalidate Parent or Overlaps
1684 if ( bNewPos ||
1685 (mnOutWidth < nOldOutWidth) || (mnOutHeight < nOldOutHeight) )
1687 vcl::Region aRegion( *pOldRegion );
1688 if ( !mpWindowImpl->mbPaintTransparent )
1689 ImplExcludeWindowRegion( aRegion );
1690 ImplClipBoundaries( aRegion, false, true );
1691 if ( !aRegion.IsEmpty() && !mpWindowImpl->mpBorderWindow )
1692 ImplInvalidateParentFrameRegion( aRegion );
1696 // adapt system objects
1697 if ( bUpdateSysObjClip )
1698 ImplUpdateSysObjClip();
1699 if ( bUpdateSysObjPos )
1700 ImplUpdateSysObjPos();
1701 if ( bNewSize && mpWindowImpl->mpSysObj )
1702 mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
1706 void Window::ImplNewInputContext()
1708 ImplSVData* pSVData = ImplGetSVData();
1709 vcl::Window* pFocusWin = pSVData->maWinData.mpFocusWin;
1710 if ( !pFocusWin )
1711 return;
1713 // Is InputContext changed?
1714 const InputContext& rInputContext = pFocusWin->GetInputContext();
1715 if ( rInputContext == pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext )
1716 return;
1718 pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext = rInputContext;
1720 SalInputContext aNewContext;
1721 const vcl::Font& rFont = rInputContext.GetFont();
1722 const OUString& rFontName = rFont.GetFamilyName();
1723 rtl::Reference<LogicalFontInstance> pFontInstance;
1724 aNewContext.mpFont = nullptr;
1725 if (!rFontName.isEmpty())
1727 OutputDevice *pFocusWinOutDev = pFocusWin->GetOutDev();
1728 Size aSize = pFocusWinOutDev->ImplLogicToDevicePixel( rFont.GetFontSize() );
1729 if ( !aSize.Height() )
1731 // only set default sizes if the font height in logical
1732 // coordinates equals 0
1733 if ( rFont.GetFontSize().Height() )
1734 aSize.setHeight( 1 );
1735 else
1736 aSize.setHeight( (12*pFocusWin->mnDPIY)/72 );
1738 pFontInstance = pFocusWin->mxFontCache->GetFontInstance( pFocusWin->mxFontCollection.get(),
1739 rFont, aSize, static_cast<float>(aSize.Height()) );
1740 if ( pFontInstance )
1741 aNewContext.mpFont = pFontInstance;
1743 aNewContext.mnOptions = rInputContext.GetOptions();
1744 pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
1747 void Window::SetModalHierarchyHdl(const Link<bool, void>& rLink)
1749 ImplGetFrame()->SetModalHierarchyHdl(rLink);
1752 void Window::SetParentToDefaultWindow()
1754 Show(false);
1755 SetParent(ImplGetDefaultWindow());
1758 KeyIndicatorState Window::GetIndicatorState() const
1760 return mpWindowImpl->mpFrame->GetIndicatorState();
1763 void Window::SimulateKeyPress( sal_uInt16 nKeyCode ) const
1765 mpWindowImpl->mpFrame->SimulateKeyPress(nKeyCode);
1768 void Window::KeyInput( const KeyEvent& rKEvt )
1770 KeyCode cod = rKEvt.GetKeyCode ();
1771 bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel;
1773 // do not respond to accelerators unless Alt is held */
1774 if (cod.GetCode () >= 0x200 && cod.GetCode () <= 0x219)
1776 if (autoacc && cod.GetModifier () != KEY_MOD2)
1777 return;
1780 NotifyEvent aNEvt( MouseNotifyEvent::KEYINPUT, this, &rKEvt );
1781 if ( !CompatNotify( aNEvt ) )
1782 mpWindowImpl->mbKeyInput = true;
1785 void Window::KeyUp( const KeyEvent& rKEvt )
1787 NotifyEvent aNEvt( MouseNotifyEvent::KEYUP, this, &rKEvt );
1788 if ( !CompatNotify( aNEvt ) )
1789 mpWindowImpl->mbKeyUp = true;
1792 void Window::Draw( OutputDevice*, const Point&, const Size&, DrawFlags )
1796 void Window::Move() {}
1798 void Window::Resize() {}
1800 void Window::Activate() {}
1802 void Window::Deactivate() {}
1804 void Window::GetFocus()
1806 if ( HasFocus() && mpWindowImpl->mpLastFocusWindow && !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) )
1808 VclPtr<vcl::Window> xWindow(this);
1809 mpWindowImpl->mpLastFocusWindow->GrabFocus();
1810 if( xWindow->IsDisposed() )
1811 return;
1814 NotifyEvent aNEvt( MouseNotifyEvent::GETFOCUS, this );
1815 CompatNotify( aNEvt );
1818 void Window::LoseFocus()
1820 NotifyEvent aNEvt( MouseNotifyEvent::LOSEFOCUS, this );
1821 CompatNotify( aNEvt );
1824 void Window::SetHelpHdl(const Link<vcl::Window&, bool>& rLink)
1826 if (mpWindowImpl) // may be called after dispose
1828 mpWindowImpl->maHelpRequestHdl = rLink;
1832 void Window::RequestHelp( const HelpEvent& rHEvt )
1834 // if Balloon-Help is requested, show the balloon
1835 // with help text set
1836 if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
1838 OUString rStr = GetHelpText();
1839 if ( rStr.isEmpty() )
1840 rStr = GetQuickHelpText();
1841 if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
1842 ImplGetParent()->RequestHelp( rHEvt );
1843 else
1845 Point aPos = GetPosPixel();
1846 if ( ImplGetParent() && !ImplIsOverlapWindow() )
1847 aPos = OutputToScreenPixel(Point(0, 0));
1848 tools::Rectangle aRect( aPos, GetSizePixel() );
1850 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aRect, rStr );
1853 else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
1855 const OUString& rStr = GetQuickHelpText();
1856 if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
1857 ImplGetParent()->RequestHelp( rHEvt );
1858 else
1860 Point aPos = GetPosPixel();
1861 if ( ImplGetParent() && !ImplIsOverlapWindow() )
1862 aPos = OutputToScreenPixel(Point(0, 0));
1863 tools::Rectangle aRect( aPos, GetSizePixel() );
1864 Help::ShowQuickHelp( this, aRect, rStr, QuickHelpFlags::CtrlText );
1867 else if (!mpWindowImpl->maHelpRequestHdl.IsSet() || mpWindowImpl->maHelpRequestHdl.Call(*this))
1869 OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
1870 if ( aStrHelpId.isEmpty() && ImplGetParent() )
1871 ImplGetParent()->RequestHelp( rHEvt );
1872 else
1874 Help* pHelp = Application::GetHelp();
1875 if ( pHelp )
1877 if( !aStrHelpId.isEmpty() )
1878 pHelp->Start( aStrHelpId, this );
1879 else
1880 pHelp->Start( OOO_HELP_INDEX, this );
1886 void Window::Command( const CommandEvent& rCEvt )
1888 CallEventListeners( VclEventId::WindowCommand, const_cast<CommandEvent *>(&rCEvt) );
1890 NotifyEvent aNEvt( MouseNotifyEvent::COMMAND, this, &rCEvt );
1891 if ( !CompatNotify( aNEvt ) )
1892 mpWindowImpl->mbCommand = true;
1895 void Window::Tracking( const TrackingEvent& rTEvt )
1898 ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
1899 if( pWrapper )
1900 pWrapper->Tracking( rTEvt );
1903 void Window::StateChanged(StateChangedType eType)
1905 switch (eType)
1907 //stuff that doesn't invalidate the layout
1908 case StateChangedType::ControlForeground:
1909 case StateChangedType::ControlBackground:
1910 case StateChangedType::UpdateMode:
1911 case StateChangedType::ReadOnly:
1912 case StateChangedType::Enable:
1913 case StateChangedType::State:
1914 case StateChangedType::Data:
1915 case StateChangedType::InitShow:
1916 case StateChangedType::ControlFocus:
1917 break;
1918 //stuff that does invalidate the layout
1919 default:
1920 queue_resize(eType);
1921 break;
1925 void Window::SetStyle( WinBits nStyle )
1927 if ( mpWindowImpl && mpWindowImpl->mnStyle != nStyle )
1929 mpWindowImpl->mnPrevStyle = mpWindowImpl->mnStyle;
1930 mpWindowImpl->mnStyle = nStyle;
1931 CompatStateChanged( StateChangedType::Style );
1935 void Window::SetExtendedStyle( WindowExtendedStyle nExtendedStyle )
1938 if ( mpWindowImpl->mnExtendedStyle != nExtendedStyle )
1940 vcl::Window* pWindow = ImplGetBorderWindow();
1941 if( ! pWindow )
1942 pWindow = this;
1943 if( pWindow->mpWindowImpl->mbFrame )
1945 SalExtStyle nExt = 0;
1946 if( nExtendedStyle & WindowExtendedStyle::Document )
1947 nExt |= SAL_FRAME_EXT_STYLE_DOCUMENT;
1948 if( nExtendedStyle & WindowExtendedStyle::DocModified )
1949 nExt |= SAL_FRAME_EXT_STYLE_DOCMODIFIED;
1951 pWindow->ImplGetFrame()->SetExtendedFrameStyle( nExt );
1953 mpWindowImpl->mnExtendedStyle = nExtendedStyle;
1957 void Window::SetBorderStyle( WindowBorderStyle nBorderStyle )
1960 if ( mpWindowImpl->mpBorderWindow )
1962 if( nBorderStyle == WindowBorderStyle::REMOVEBORDER &&
1963 ! mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame &&
1964 mpWindowImpl->mpBorderWindow->mpWindowImpl->mpParent
1967 // this is a little awkward: some controls (e.g. svtools ProgressBar)
1968 // cannot avoid getting constructed with WB_BORDER but want to disable
1969 // borders in case of NWF drawing. So they need a method to remove their border window
1970 VclPtr<vcl::Window> pBorderWin = mpWindowImpl->mpBorderWindow;
1971 // remove us as border window's client
1972 pBorderWin->mpWindowImpl->mpClientWindow = nullptr;
1973 mpWindowImpl->mpBorderWindow = nullptr;
1974 mpWindowImpl->mpRealParent = pBorderWin->mpWindowImpl->mpParent;
1975 // reparent us above the border window
1976 SetParent( pBorderWin->mpWindowImpl->mpParent );
1977 // set us to the position and size of our previous border
1978 Point aBorderPos( pBorderWin->GetPosPixel() );
1979 Size aBorderSize( pBorderWin->GetSizePixel() );
1980 setPosSizePixel( aBorderPos.X(), aBorderPos.Y(), aBorderSize.Width(), aBorderSize.Height() );
1981 // release border window
1982 pBorderWin.disposeAndClear();
1984 // set new style bits
1985 SetStyle( GetStyle() & (~WB_BORDER) );
1987 else
1989 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
1990 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetBorderStyle( nBorderStyle );
1991 else
1992 mpWindowImpl->mpBorderWindow->SetBorderStyle( nBorderStyle );
1997 WindowBorderStyle Window::GetBorderStyle() const
2000 if ( mpWindowImpl->mpBorderWindow )
2002 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2003 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorderStyle();
2004 else
2005 return mpWindowImpl->mpBorderWindow->GetBorderStyle();
2008 return WindowBorderStyle::NONE;
2011 long Window::CalcTitleWidth() const
2014 if ( mpWindowImpl->mpBorderWindow )
2016 if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW )
2017 return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->CalcTitleWidth();
2018 else
2019 return mpWindowImpl->mpBorderWindow->CalcTitleWidth();
2021 else if ( mpWindowImpl->mbFrame && (mpWindowImpl->mnStyle & WB_MOVEABLE) )
2023 // we guess the width for frame windows as we do not know the
2024 // border of external dialogs
2025 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
2026 vcl::Font aFont = GetFont();
2027 const_cast<vcl::Window*>(this)->SetPointFont(*const_cast<Window*>(this), rStyleSettings.GetTitleFont());
2028 long nTitleWidth = GetTextWidth( GetText() );
2029 const_cast<vcl::Window*>(this)->SetFont( aFont );
2030 nTitleWidth += rStyleSettings.GetTitleHeight() * 3;
2031 nTitleWidth += StyleSettings::GetBorderSize() * 2;
2032 nTitleWidth += 10;
2033 return nTitleWidth;
2036 return 0;
2039 void Window::SetInputContext( const InputContext& rInputContext )
2042 mpWindowImpl->maInputContext = rInputContext;
2043 if ( !mpWindowImpl->mbInFocusHdl && HasFocus() )
2044 ImplNewInputContext();
2047 void Window::PostExtTextInputEvent(VclEventId nType, const OUString& rText)
2049 switch (nType)
2051 case VclEventId::ExtTextInput:
2053 std::unique_ptr<ExtTextInputAttr[]> pAttr(new ExtTextInputAttr[rText.getLength()]);
2054 for (int i = 0; i < rText.getLength(); ++i) {
2055 pAttr[i] = ExtTextInputAttr::Underline;
2057 SalExtTextInputEvent aEvent { rText, pAttr.get(), rText.getLength(), EXTTEXTINPUT_CURSOR_OVERWRITE };
2058 ImplWindowFrameProc(this, SalEvent::ExtTextInput, &aEvent);
2060 break;
2061 case VclEventId::EndExtTextInput:
2062 ImplWindowFrameProc(this, SalEvent::EndExtTextInput, nullptr);
2063 break;
2064 default:
2065 assert(false);
2069 void Window::EndExtTextInput()
2071 if ( mpWindowImpl->mbExtTextInput )
2072 ImplGetFrame()->EndExtTextInput( EndExtTextInputFlags::Complete );
2075 void Window::SetCursorRect( const tools::Rectangle* pRect, long nExtTextInputWidth )
2078 ImplWinData* pWinData = ImplGetWinData();
2079 if ( pWinData->mpCursorRect )
2081 if ( pRect )
2082 pWinData->mpCursorRect = *pRect;
2083 else
2084 pWinData->mpCursorRect.reset();
2086 else
2088 if ( pRect )
2089 pWinData->mpCursorRect = *pRect;
2092 pWinData->mnCursorExtWidth = nExtTextInputWidth;
2096 const tools::Rectangle* Window::GetCursorRect() const
2099 ImplWinData* pWinData = ImplGetWinData();
2100 return pWinData->mpCursorRect ? &*pWinData->mpCursorRect : nullptr;
2103 long Window::GetCursorExtTextInputWidth() const
2106 ImplWinData* pWinData = ImplGetWinData();
2107 return pWinData->mnCursorExtWidth;
2110 void Window::SetCompositionCharRect( const tools::Rectangle* pRect, long nCompositionLength, bool bVertical ) {
2112 ImplWinData* pWinData = ImplGetWinData();
2113 pWinData->mpCompositionCharRects.reset();
2114 pWinData->mbVertical = bVertical;
2115 pWinData->mnCompositionCharRects = nCompositionLength;
2116 if ( pRect && (nCompositionLength > 0) )
2118 pWinData->mpCompositionCharRects.reset( new tools::Rectangle[nCompositionLength] );
2119 for (long i = 0; i < nCompositionLength; ++i)
2120 pWinData->mpCompositionCharRects[i] = pRect[i];
2124 void Window::CollectChildren(::std::vector<vcl::Window *>& rAllChildren )
2126 rAllChildren.push_back( this );
2128 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2129 while ( pChild )
2131 pChild->CollectChildren( rAllChildren );
2132 pChild = pChild->mpWindowImpl->mpNext;
2136 void Window::SetPointFont(vcl::RenderContext& rRenderContext, const vcl::Font& rFont)
2138 vcl::Font aFont = rFont;
2139 ImplPointToLogic(rRenderContext, aFont);
2140 rRenderContext.SetFont(aFont);
2143 vcl::Font Window::GetPointFont(vcl::RenderContext const & rRenderContext) const
2145 vcl::Font aFont = rRenderContext.GetFont();
2146 ImplLogicToPoint(rRenderContext, aFont);
2147 return aFont;
2150 void Window::Show(bool bVisible, ShowFlags nFlags)
2152 if ( IsDisposed() || mpWindowImpl->mbVisible == bVisible )
2153 return;
2155 VclPtr<vcl::Window> xWindow(this);
2157 bool bRealVisibilityChanged = false;
2158 mpWindowImpl->mbVisible = bVisible;
2160 if ( !bVisible )
2162 ImplHideAllOverlaps();
2163 if( xWindow->IsDisposed() )
2164 return;
2166 if ( mpWindowImpl->mpBorderWindow )
2168 bool bOldUpdate = mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate;
2169 if ( mpWindowImpl->mbNoParentUpdate )
2170 mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = true;
2171 mpWindowImpl->mpBorderWindow->Show( false, nFlags );
2172 mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = bOldUpdate;
2174 else if ( mpWindowImpl->mbFrame )
2176 mpWindowImpl->mbSuppressAccessibilityEvents = true;
2177 mpWindowImpl->mpFrame->Show( false );
2180 CompatStateChanged( StateChangedType::Visible );
2182 if ( mpWindowImpl->mbReallyVisible )
2184 if ( mpWindowImpl->mbInitWinClipRegion )
2185 ImplInitWinClipRegion();
2187 vcl::Region aInvRegion = mpWindowImpl->maWinClipRegion;
2189 if( xWindow->IsDisposed() )
2190 return;
2192 bRealVisibilityChanged = mpWindowImpl->mbReallyVisible;
2193 ImplResetReallyVisible();
2194 ImplSetClipFlag();
2196 if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
2198 // convert focus
2199 if ( !(nFlags & ShowFlags::NoFocusChange) && HasChildPathFocus() )
2201 if ( mpWindowImpl->mpOverlapWindow->IsEnabled() &&
2202 mpWindowImpl->mpOverlapWindow->IsInputEnabled() &&
2203 ! mpWindowImpl->mpOverlapWindow->IsInModalMode()
2205 mpWindowImpl->mpOverlapWindow->GrabFocus();
2209 if ( !mpWindowImpl->mbFrame )
2211 if( mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mbEnableNativeWidget )
2214 * #i48371# native theming: some themes draw outside the control
2215 * area we tell them to (bad thing, but we cannot do much about it ).
2216 * On hiding these controls they get invalidated with their window rectangle
2217 * which leads to the parts outside the control area being left and not
2218 * invalidated. Workaround: invalidate an area on the parent, too
2220 const int workaround_border = 5;
2221 tools::Rectangle aBounds( aInvRegion.GetBoundRect() );
2222 aBounds.AdjustLeft( -workaround_border );
2223 aBounds.AdjustTop( -workaround_border );
2224 aBounds.AdjustRight(workaround_border );
2225 aBounds.AdjustBottom(workaround_border );
2226 aInvRegion = aBounds;
2228 if ( !mpWindowImpl->mbNoParentUpdate )
2230 if ( !aInvRegion.IsEmpty() )
2231 ImplInvalidateParentFrameRegion( aInvRegion );
2233 ImplGenerateMouseMove();
2237 else
2239 // inherit native widget flag for form controls
2240 // required here, because frames never show up in the child hierarchy - which should be fixed...
2241 // eg, the drop down of a combobox which is a system floating window
2242 if( mpWindowImpl->mbFrame && GetParent() && GetParent()->IsCompoundControl() &&
2243 GetParent()->IsNativeWidgetEnabled() != IsNativeWidgetEnabled() &&
2244 !(GetStyle() & WB_TOOLTIPWIN) )
2246 EnableNativeWidget( GetParent()->IsNativeWidgetEnabled() );
2249 if ( mpWindowImpl->mbCallMove )
2251 ImplCallMove();
2253 if ( mpWindowImpl->mbCallResize )
2255 ImplCallResize();
2258 CompatStateChanged( StateChangedType::Visible );
2260 vcl::Window* pTestParent;
2261 if ( ImplIsOverlapWindow() )
2262 pTestParent = mpWindowImpl->mpOverlapWindow;
2263 else
2264 pTestParent = ImplGetParent();
2265 if ( mpWindowImpl->mbFrame || pTestParent->mpWindowImpl->mbReallyVisible )
2267 // if a window becomes visible, send all child windows a StateChange,
2268 // such that these can initialise themselves
2269 ImplCallInitShow();
2271 // If it is a SystemWindow it automatically pops up on top of
2272 // all other windows if needed.
2273 if ( ImplIsOverlapWindow() && !(nFlags & ShowFlags::NoActivate) )
2275 ImplStartToTop(( nFlags & ShowFlags::ForegroundTask ) ? ToTopFlags::ForegroundTask : ToTopFlags::NONE );
2276 ImplFocusToTop( ToTopFlags::NONE, false );
2279 // adjust mpWindowImpl->mbReallyVisible
2280 bRealVisibilityChanged = !mpWindowImpl->mbReallyVisible;
2281 ImplSetReallyVisible();
2283 // assure clip rectangles will be recalculated
2284 ImplSetClipFlag();
2286 if ( !mpWindowImpl->mbFrame )
2288 InvalidateFlags nInvalidateFlags = InvalidateFlags::Children;
2289 if( ! IsPaintTransparent() )
2290 nInvalidateFlags |= InvalidateFlags::NoTransparent;
2291 ImplInvalidate( nullptr, nInvalidateFlags );
2292 ImplGenerateMouseMove();
2296 if ( mpWindowImpl->mpBorderWindow )
2297 mpWindowImpl->mpBorderWindow->Show( true, nFlags );
2298 else if ( mpWindowImpl->mbFrame )
2300 // #106431#, hide SplashScreen
2301 ImplSVData* pSVData = ImplGetSVData();
2302 if ( !pSVData->mpIntroWindow )
2304 // The right way would be just to call this (not even in the 'if')
2305 auto pApp = GetpApp();
2306 if ( pApp )
2307 pApp->InitFinished();
2309 else if ( !ImplIsWindowOrChild( pSVData->mpIntroWindow ) )
2311 // ... but the VCL splash is broken, and it needs this
2312 // (for ./soffice .uno:NewDoc)
2313 pSVData->mpIntroWindow->Hide();
2316 //SAL_WARN_IF( mpWindowImpl->mbSuppressAccessibilityEvents, "vcl", "Window::Show() - Frame reactivated");
2317 mpWindowImpl->mbSuppressAccessibilityEvents = false;
2319 mpWindowImpl->mbPaintFrame = true;
2320 if (!Application::IsHeadlessModeEnabled())
2322 bool bNoActivate(nFlags & (ShowFlags::NoActivate|ShowFlags::NoFocusChange));
2323 mpWindowImpl->mpFrame->Show( true, bNoActivate );
2325 if( xWindow->IsDisposed() )
2326 return;
2328 // Query the correct size of the window, if we are waiting for
2329 // a system resize
2330 if ( mpWindowImpl->mbWaitSystemResize )
2332 long nOutWidth;
2333 long nOutHeight;
2334 mpWindowImpl->mpFrame->GetClientSize( nOutWidth, nOutHeight );
2335 ImplHandleResize( this, nOutWidth, nOutHeight );
2338 if (mpWindowImpl->mpFrameData->mpBuffer && mpWindowImpl->mpFrameData->mpBuffer->GetOutputSizePixel() != GetOutputSizePixel())
2339 // Make sure that the buffer size matches the window size, even if no resize was needed.
2340 mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(GetOutputSizePixel());
2343 if( xWindow->IsDisposed() )
2344 return;
2346 ImplShowAllOverlaps();
2349 if( xWindow->IsDisposed() )
2350 return;
2352 // the SHOW/HIDE events also serve as indicators to send child creation/destroy events to the access bridge
2353 // However, the access bridge only uses this event if the data member is not NULL (it's kind of a hack that
2354 // we re-use the SHOW/HIDE events this way, with this particular semantics).
2355 // Since #104887#, the notifications for the access bridge are done in Impl(Set|Reset)ReallyVisible. Here, we
2356 // now only notify with a NULL data pointer, for all other clients except the access bridge.
2357 if ( !bRealVisibilityChanged )
2358 CallEventListeners( mpWindowImpl->mbVisible ? VclEventId::WindowShow : VclEventId::WindowHide );
2359 if( xWindow->IsDisposed() )
2360 return;
2364 Size Window::GetSizePixel() const
2366 if (!mpWindowImpl)
2368 SAL_WARN("vcl.layout", "WTF no windowimpl");
2369 return Size(0,0);
2372 // #i43257# trigger pending resize handler to assure correct window sizes
2373 if( mpWindowImpl->mpFrameData->maResizeIdle.IsActive() )
2375 VclPtr<vcl::Window> xWindow( const_cast<Window*>(this) );
2376 mpWindowImpl->mpFrameData->maResizeIdle.Stop();
2377 mpWindowImpl->mpFrameData->maResizeIdle.Invoke( nullptr );
2378 if( xWindow->IsDisposed() )
2379 return Size(0,0);
2382 return Size( mnOutWidth+mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder,
2383 mnOutHeight+mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder );
2386 void Window::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
2387 sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
2389 rLeftBorder = mpWindowImpl->mnLeftBorder;
2390 rTopBorder = mpWindowImpl->mnTopBorder;
2391 rRightBorder = mpWindowImpl->mnRightBorder;
2392 rBottomBorder = mpWindowImpl->mnBottomBorder;
2395 void Window::Enable( bool bEnable, bool bChild )
2397 if ( IsDisposed() )
2398 return;
2400 if ( !bEnable )
2402 // the tracking mode will be stopped or the capture will be stolen
2403 // when a window is disabled,
2404 if ( IsTracking() )
2405 EndTracking( TrackingEventFlags::Cancel );
2406 if ( IsMouseCaptured() )
2407 ReleaseMouse();
2408 // try to pass focus to the next control
2409 // if the window has focus and is contained in the dialog control
2410 // mpWindowImpl->mbDisabled should only be set after a call of ImplDlgCtrlNextWindow().
2411 // Otherwise ImplDlgCtrlNextWindow() should be used
2412 if ( HasFocus() )
2413 ImplDlgCtrlNextWindow();
2416 if ( mpWindowImpl->mpBorderWindow )
2418 mpWindowImpl->mpBorderWindow->Enable( bEnable, false );
2419 if ( (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) &&
2420 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
2421 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->Enable( bEnable );
2424 // #i56102# restore app focus win in case the
2425 // window was disabled when the frame focus changed
2426 ImplSVData* pSVData = ImplGetSVData();
2427 if( bEnable &&
2428 pSVData->maWinData.mpFocusWin == nullptr &&
2429 mpWindowImpl->mpFrameData->mbHasFocus &&
2430 mpWindowImpl->mpFrameData->mpFocusWin == this )
2431 pSVData->maWinData.mpFocusWin = this;
2433 if ( mpWindowImpl->mbDisabled != !bEnable )
2435 mpWindowImpl->mbDisabled = !bEnable;
2436 if ( mpWindowImpl->mpSysObj )
2437 mpWindowImpl->mpSysObj->Enable( bEnable && !mpWindowImpl->mbInputDisabled );
2438 CompatStateChanged( StateChangedType::Enable );
2440 CallEventListeners( bEnable ? VclEventId::WindowEnabled : VclEventId::WindowDisabled );
2443 if ( bChild )
2445 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2446 while ( pChild )
2448 pChild->Enable( bEnable, bChild );
2449 pChild = pChild->mpWindowImpl->mpNext;
2453 if ( IsReallyVisible() )
2454 ImplGenerateMouseMove();
2457 void Window::SetCallHandlersOnInputDisabled( bool bCall )
2459 mpWindowImpl->mbCallHandlersDuringInputDisabled = bCall;
2461 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2462 while ( pChild )
2464 pChild->SetCallHandlersOnInputDisabled( bCall );
2465 pChild = pChild->mpWindowImpl->mpNext;
2469 bool Window::IsCallHandlersOnInputDisabled() const
2471 return mpWindowImpl->mbCallHandlersDuringInputDisabled;
2474 void Window::EnableInput( bool bEnable, bool bChild )
2476 if (!mpWindowImpl)
2477 return;
2479 bool bNotify = (bEnable != mpWindowImpl->mbInputDisabled);
2480 if ( mpWindowImpl->mpBorderWindow )
2482 mpWindowImpl->mpBorderWindow->EnableInput( bEnable, false );
2483 if ( (mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW) &&
2484 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
2485 static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->EnableInput( bEnable );
2488 if ( (! bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled) ||
2489 ( bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputDisabled) )
2491 // automatically stop the tracking mode or steal capture
2492 // if the window is disabled
2493 if ( !bEnable )
2495 if ( IsTracking() )
2496 EndTracking( TrackingEventFlags::Cancel );
2497 if ( IsMouseCaptured() )
2498 ReleaseMouse();
2501 if ( mpWindowImpl->mbInputDisabled != !bEnable )
2503 mpWindowImpl->mbInputDisabled = !bEnable;
2504 if ( mpWindowImpl->mpSysObj )
2505 mpWindowImpl->mpSysObj->Enable( !mpWindowImpl->mbDisabled && bEnable );
2509 // #i56102# restore app focus win in case the
2510 // window was disabled when the frame focus changed
2511 ImplSVData* pSVData = ImplGetSVData();
2512 if( bEnable &&
2513 pSVData->maWinData.mpFocusWin == nullptr &&
2514 mpWindowImpl->mpFrameData->mbHasFocus &&
2515 mpWindowImpl->mpFrameData->mpFocusWin == this )
2516 pSVData->maWinData.mpFocusWin = this;
2518 if ( bChild )
2520 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2521 while ( pChild )
2523 pChild->EnableInput( bEnable, bChild );
2524 pChild = pChild->mpWindowImpl->mpNext;
2528 if ( IsReallyVisible() )
2529 ImplGenerateMouseMove();
2531 // #104827# notify parent
2532 if ( bNotify && bEnable )
2534 NotifyEvent aNEvt( MouseNotifyEvent::INPUTENABLE, this );
2535 CompatNotify( aNEvt );
2539 void Window::EnableInput( bool bEnable, const vcl::Window* pExcludeWindow )
2541 if (!mpWindowImpl)
2542 return;
2544 EnableInput( bEnable );
2546 // pExecuteWindow is the first Overlap-Frame --> if this
2547 // shouldn't be the case, then this must be changed in dialog.cxx
2548 if( pExcludeWindow )
2549 pExcludeWindow = pExcludeWindow->ImplGetFirstOverlapWindow();
2550 vcl::Window* pSysWin = mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mpFirstOverlap;
2551 while ( pSysWin )
2553 // Is Window in the path from this window
2554 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pSysWin, true ) )
2556 // Is Window not in the exclude window path or not the
2557 // exclude window, then change the status
2558 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pSysWin, true ) )
2559 pSysWin->EnableInput( bEnable );
2561 pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
2564 // enable/disable floating system windows as well
2565 vcl::Window* pFrameWin = ImplGetSVData()->maWinData.mpFirstFrame;
2566 while ( pFrameWin )
2568 if( pFrameWin->ImplIsFloatingWindow() )
2570 // Is Window in the path from this window
2571 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pFrameWin, true ) )
2573 // Is Window not in the exclude window path or not the
2574 // exclude window, then change the status
2575 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pFrameWin, true ) )
2576 pFrameWin->EnableInput( bEnable );
2579 pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
2582 // the same for ownerdraw floating windows
2583 if( mpWindowImpl->mbFrame )
2585 ::std::vector< VclPtr<vcl::Window> >& rList = mpWindowImpl->mpFrameData->maOwnerDrawList;
2586 for (auto const& elem : rList)
2588 // Is Window in the path from this window
2589 if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( elem, true ) )
2591 // Is Window not in the exclude window path or not the
2592 // exclude window, then change the status
2593 if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( elem, true ) )
2594 elem->EnableInput( bEnable );
2600 void Window::AlwaysEnableInput( bool bAlways, bool bChild )
2603 if ( mpWindowImpl->mpBorderWindow )
2604 mpWindowImpl->mpBorderWindow->AlwaysEnableInput( bAlways, false );
2606 if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled )
2608 mpWindowImpl->meAlwaysInputMode = AlwaysInputEnabled;
2609 EnableInput(true, false);
2611 else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled )
2613 mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
2616 if ( bChild )
2618 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2619 while ( pChild )
2621 pChild->AlwaysEnableInput( bAlways, bChild );
2622 pChild = pChild->mpWindowImpl->mpNext;
2627 void Window::AlwaysDisableInput( bool bAlways, bool bChild )
2630 if ( mpWindowImpl->mpBorderWindow )
2631 mpWindowImpl->mpBorderWindow->AlwaysDisableInput( bAlways, false );
2633 if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputDisabled )
2635 mpWindowImpl->meAlwaysInputMode = AlwaysInputDisabled;
2636 EnableInput(false, false);
2638 else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputDisabled )
2640 mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
2643 if ( bChild )
2645 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
2646 while ( pChild )
2648 pChild->AlwaysDisableInput( bAlways, bChild );
2649 pChild = pChild->mpWindowImpl->mpNext;
2654 void Window::SetActivateMode( ActivateModeFlags nMode )
2657 if ( mpWindowImpl->mpBorderWindow )
2658 mpWindowImpl->mpBorderWindow->SetActivateMode( nMode );
2660 if ( mpWindowImpl->mnActivateMode != nMode )
2662 mpWindowImpl->mnActivateMode = nMode;
2664 // possibly trigger Deactivate/Activate
2665 if ( mpWindowImpl->mnActivateMode != ActivateModeFlags::NONE )
2667 if ( (mpWindowImpl->mbActive || (GetType() == WindowType::BORDERWINDOW)) &&
2668 !HasChildPathFocus( true ) )
2670 mpWindowImpl->mbActive = false;
2671 Deactivate();
2674 else
2676 if ( !mpWindowImpl->mbActive || (GetType() == WindowType::BORDERWINDOW) )
2678 mpWindowImpl->mbActive = true;
2679 Activate();
2685 void Window::setPosSizePixel( long nX, long nY,
2686 long nWidth, long nHeight, PosSizeFlags nFlags )
2688 bool bHasValidSize = !mpWindowImpl->mbDefSize;
2690 if ( nFlags & PosSizeFlags::Pos )
2691 mpWindowImpl->mbDefPos = false;
2692 if ( nFlags & PosSizeFlags::Size )
2693 mpWindowImpl->mbDefSize = false;
2695 // The top BorderWindow is the window which is to be positioned
2696 VclPtr<vcl::Window> pWindow = this;
2697 while ( pWindow->mpWindowImpl->mpBorderWindow )
2698 pWindow = pWindow->mpWindowImpl->mpBorderWindow;
2700 if ( pWindow->mpWindowImpl->mbFrame )
2702 // Note: if we're positioning a frame, the coordinates are interpreted
2703 // as being the top-left corner of the window's client area and NOT
2704 // as the position of the border ! (due to limitations of several UNIX window managers)
2705 long nOldWidth = pWindow->mnOutWidth;
2707 if ( !(nFlags & PosSizeFlags::Width) )
2708 nWidth = pWindow->mnOutWidth;
2709 if ( !(nFlags & PosSizeFlags::Height) )
2710 nHeight = pWindow->mnOutHeight;
2712 sal_uInt16 nSysFlags=0;
2713 VclPtr<vcl::Window> pParent = GetParent();
2714 VclPtr<vcl::Window> pWinParent = pWindow->GetParent();
2716 if( nFlags & PosSizeFlags::Width )
2717 nSysFlags |= SAL_FRAME_POSSIZE_WIDTH;
2718 if( nFlags & PosSizeFlags::Height )
2719 nSysFlags |= SAL_FRAME_POSSIZE_HEIGHT;
2720 if( nFlags & PosSizeFlags::X )
2722 nSysFlags |= SAL_FRAME_POSSIZE_X;
2723 if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
2725 nX += pWinParent->mnOutOffX;
2727 if( pParent && pParent->ImplIsAntiparallel() )
2729 tools::Rectangle aRect( Point ( nX, nY ), Size( nWidth, nHeight ) );
2730 const OutputDevice *pParentOutDev = pParent->GetOutDev();
2731 pParentOutDev->ReMirror( aRect );
2732 nX = aRect.Left();
2735 if( !(nFlags & PosSizeFlags::X) && bHasValidSize && pWindow->mpWindowImpl->mpFrame->maGeometry.nWidth )
2737 // RTL: make sure the old right aligned position is not changed
2738 // system windows will always grow to the right
2739 if ( pWinParent )
2741 OutputDevice *pParentOutDev = pWinParent->GetOutDev();
2742 if( pParentOutDev->HasMirroredGraphics() )
2744 const SalFrameGeometry& aSysGeometry = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2745 const SalFrameGeometry& aParentSysGeometry =
2746 pWinParent->mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2747 long myWidth = nOldWidth;
2748 if( !myWidth )
2749 myWidth = aSysGeometry.nWidth;
2750 if( !myWidth )
2751 myWidth = nWidth;
2752 nFlags |= PosSizeFlags::X;
2753 nSysFlags |= SAL_FRAME_POSSIZE_X;
2754 nX = aParentSysGeometry.nX - aSysGeometry.nLeftDecoration + aParentSysGeometry.nWidth
2755 - myWidth - 1 - aSysGeometry.nX;
2759 if( nFlags & PosSizeFlags::Y )
2761 nSysFlags |= SAL_FRAME_POSSIZE_Y;
2762 if( pWinParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
2764 nY += pWinParent->mnOutOffY;
2768 if( nSysFlags & (SAL_FRAME_POSSIZE_WIDTH|SAL_FRAME_POSSIZE_HEIGHT) )
2770 // check for min/max client size and adjust size accordingly
2771 // otherwise it may happen that the resize event is ignored, i.e. the old size remains
2772 // unchanged but ImplHandleResize() is called with the wrong size
2773 SystemWindow *pSystemWindow = dynamic_cast< SystemWindow* >( pWindow.get() );
2774 if( pSystemWindow )
2776 Size aMinSize = pSystemWindow->GetMinOutputSizePixel();
2777 Size aMaxSize = pSystemWindow->GetMaxOutputSizePixel();
2778 if( nWidth < aMinSize.Width() )
2779 nWidth = aMinSize.Width();
2780 if( nHeight < aMinSize.Height() )
2781 nHeight = aMinSize.Height();
2783 if( nWidth > aMaxSize.Width() )
2784 nWidth = aMaxSize.Width();
2785 if( nHeight > aMaxSize.Height() )
2786 nHeight = aMaxSize.Height();
2790 pWindow->mpWindowImpl->mpFrame->SetPosSize( nX, nY, nWidth, nHeight, nSysFlags );
2792 // Resize should be called directly. If we haven't
2793 // set the correct size, we get a second resize from
2794 // the system with the correct size. This can be happened
2795 // if the size is too small or too large.
2796 ImplHandleResize( pWindow, nWidth, nHeight );
2798 else
2800 pWindow->ImplPosSizeWindow( nX, nY, nWidth, nHeight, nFlags );
2801 if ( IsReallyVisible() )
2802 ImplGenerateMouseMove();
2806 Point Window::GetPosPixel() const
2808 return mpWindowImpl->maPos;
2811 tools::Rectangle Window::GetDesktopRectPixel() const
2813 tools::Rectangle rRect;
2814 mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrame->GetWorkArea( rRect );
2815 return rRect;
2818 Point Window::OutputToScreenPixel( const Point& rPos ) const
2820 // relative to top level parent
2821 return Point( rPos.X()+mnOutOffX, rPos.Y()+mnOutOffY );
2824 Point Window::ScreenToOutputPixel( const Point& rPos ) const
2826 // relative to top level parent
2827 return Point( rPos.X()-mnOutOffX, rPos.Y()-mnOutOffY );
2830 long Window::ImplGetUnmirroredOutOffX()
2832 // revert mnOutOffX changes that were potentially made in ImplPosSizeWindow
2833 long offx = mnOutOffX;
2834 OutputDevice *pOutDev = GetOutDev();
2835 if( pOutDev->HasMirroredGraphics() )
2837 if( mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
2839 if ( !ImplIsOverlapWindow() )
2840 offx -= mpWindowImpl->mpParent->mnOutOffX;
2842 offx = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - offx;
2844 if ( !ImplIsOverlapWindow() )
2845 offx += mpWindowImpl->mpParent->mnOutOffX;
2849 return offx;
2852 // normalized screen pixel are independent of mirroring
2853 Point Window::OutputToNormalizedScreenPixel( const Point& rPos ) const
2855 // relative to top level parent
2856 long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX();
2857 return Point( rPos.X()+offx, rPos.Y()+mnOutOffY );
2860 Point Window::NormalizedScreenToOutputPixel( const Point& rPos ) const
2862 // relative to top level parent
2863 long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX();
2864 return Point( rPos.X()-offx, rPos.Y()-mnOutOffY );
2867 Point Window::OutputToAbsoluteScreenPixel( const Point& rPos ) const
2869 // relative to the screen
2870 Point p = OutputToScreenPixel( rPos );
2871 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2872 p.AdjustX(g.nX );
2873 p.AdjustY(g.nY );
2874 return p;
2877 Point Window::AbsoluteScreenToOutputPixel( const Point& rPos ) const
2879 // relative to the screen
2880 Point p = ScreenToOutputPixel( rPos );
2881 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2882 p.AdjustX( -(g.nX) );
2883 p.AdjustY( -(g.nY) );
2884 return p;
2887 tools::Rectangle Window::ImplOutputToUnmirroredAbsoluteScreenPixel( const tools::Rectangle &rRect ) const
2889 // this method creates unmirrored screen coordinates to be compared with the desktop
2890 // and is used for positioning of RTL popup windows correctly on the screen
2891 SalFrameGeometry g = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
2893 Point p1 = OutputToScreenPixel( rRect.TopRight() );
2894 p1.setX( g.nX+g.nWidth-p1.X() );
2895 p1.AdjustY(g.nY );
2897 Point p2 = OutputToScreenPixel( rRect.BottomLeft() );
2898 p2.setX( g.nX+g.nWidth-p2.X() );
2899 p2.AdjustY(g.nY );
2901 return tools::Rectangle( p1, p2 );
2904 tools::Rectangle Window::GetWindowExtentsRelative( vcl::Window *pRelativeWindow ) const
2906 // with decoration
2907 return ImplGetWindowExtentsRelative( pRelativeWindow, false );
2910 tools::Rectangle Window::GetClientWindowExtentsRelative() const
2912 // without decoration
2913 return ImplGetWindowExtentsRelative( nullptr, true );
2916 tools::Rectangle Window::ImplGetWindowExtentsRelative( vcl::Window *pRelativeWindow, bool bClientOnly ) const
2918 SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
2919 // make sure we use the extent of our border window,
2920 // otherwise we miss a few pixels
2921 const vcl::Window *pWin = (!bClientOnly && mpWindowImpl->mpBorderWindow) ? mpWindowImpl->mpBorderWindow : this;
2923 Point aPos( pWin->OutputToScreenPixel( Point(0,0) ) );
2924 aPos.AdjustX(g.nX );
2925 aPos.AdjustY(g.nY );
2926 Size aSize ( pWin->GetSizePixel() );
2927 // #104088# do not add decoration to the workwindow to be compatible to java accessibility api
2928 if( !bClientOnly && (mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && GetType() != WindowType::WORKWINDOW)) )
2930 aPos.AdjustX( -sal_Int32(g.nLeftDecoration) );
2931 aPos.AdjustY( -sal_Int32(g.nTopDecoration) );
2932 aSize.AdjustWidth(g.nLeftDecoration + g.nRightDecoration );
2933 aSize.AdjustHeight(g.nTopDecoration + g.nBottomDecoration );
2935 if( pRelativeWindow )
2937 // #106399# express coordinates relative to borderwindow
2938 vcl::Window *pRelWin = (!bClientOnly && pRelativeWindow->mpWindowImpl->mpBorderWindow) ? pRelativeWindow->mpWindowImpl->mpBorderWindow.get() : pRelativeWindow;
2939 aPos = pRelWin->AbsoluteScreenToOutputPixel( aPos );
2941 return tools::Rectangle( aPos, aSize );
2944 void Window::Scroll( long nHorzScroll, long nVertScroll, ScrollFlags nFlags )
2947 ImplScroll( tools::Rectangle( Point( mnOutOffX, mnOutOffY ),
2948 Size( mnOutWidth, mnOutHeight ) ),
2949 nHorzScroll, nVertScroll, nFlags & ~ScrollFlags::Clip );
2952 void Window::Scroll( long nHorzScroll, long nVertScroll,
2953 const tools::Rectangle& rRect, ScrollFlags nFlags )
2955 OutputDevice *pOutDev = GetOutDev();
2956 tools::Rectangle aRect = pOutDev->ImplLogicToDevicePixel( rRect );
2957 aRect.Intersection( tools::Rectangle( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ) );
2958 if ( !aRect.IsEmpty() )
2959 ImplScroll( aRect, nHorzScroll, nVertScroll, nFlags );
2962 void Window::Flush()
2964 if (mpWindowImpl)
2966 const tools::Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
2967 mpWindowImpl->mpFrame->Flush( aWinRect );
2971 void Window::SetUpdateMode( bool bUpdate )
2973 if (mpWindowImpl)
2975 mpWindowImpl->mbNoUpdate = !bUpdate;
2976 CompatStateChanged( StateChangedType::UpdateMode );
2980 void Window::GrabFocus()
2982 ImplGrabFocus( GetFocusFlags::NONE );
2985 bool Window::HasFocus() const
2987 return (this == ImplGetSVData()->maWinData.mpFocusWin);
2990 void Window::GrabFocusToDocument()
2992 ImplGrabFocusToDocument(GetFocusFlags::NONE);
2995 VclPtr<vcl::Window> Window::GetFocusedWindow() const
2997 if (mpWindowImpl && mpWindowImpl->mpFrameData)
2998 return mpWindowImpl->mpFrameData->mpFocusWin;
2999 else
3000 return VclPtr<vcl::Window>();
3003 void Window::SetFakeFocus( bool bFocus )
3005 ImplGetWindowImpl()->mbFakeFocusSet = bFocus;
3008 bool Window::HasChildPathFocus( bool bSystemWindow ) const
3011 vcl::Window* pFocusWin = ImplGetSVData()->maWinData.mpFocusWin;
3012 if ( pFocusWin )
3013 return ImplIsWindowOrChild( pFocusWin, bSystemWindow );
3014 return false;
3017 void Window::SetCursor( vcl::Cursor* pCursor )
3020 if ( mpWindowImpl->mpCursor != pCursor )
3022 if ( mpWindowImpl->mpCursor )
3023 mpWindowImpl->mpCursor->ImplHide();
3024 mpWindowImpl->mpCursor = pCursor;
3025 if ( pCursor )
3026 pCursor->ImplShow();
3030 void Window::SetText( const OUString& rStr )
3032 if (!mpWindowImpl || rStr == mpWindowImpl->maText)
3033 return;
3035 OUString oldTitle( mpWindowImpl->maText );
3036 mpWindowImpl->maText = rStr;
3038 if ( mpWindowImpl->mpBorderWindow )
3039 mpWindowImpl->mpBorderWindow->SetText( rStr );
3040 else if ( mpWindowImpl->mbFrame )
3041 mpWindowImpl->mpFrame->SetTitle( rStr );
3043 CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle );
3045 // #107247# needed for accessibility
3046 // The VclEventId::WindowFrameTitleChanged is (mis)used to notify accessible name changes.
3047 // Therefore a window, which is labeled by this window, must also notify an accessible
3048 // name change.
3049 if ( IsReallyVisible() )
3051 vcl::Window* pWindow = GetAccessibleRelationLabelFor();
3052 if ( pWindow && pWindow != this )
3053 pWindow->CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle );
3056 CompatStateChanged( StateChangedType::Text );
3059 OUString Window::GetText() const
3062 return mpWindowImpl->maText;
3065 OUString Window::GetDisplayText() const
3068 return GetText();
3071 const Wallpaper& Window::GetDisplayBackground() const
3073 // FIXME: fix issue 52349, need to fix this really in
3074 // all NWF enabled controls
3075 const ToolBox* pTB = dynamic_cast<const ToolBox*>(this);
3076 if( pTB && IsNativeWidgetEnabled() )
3077 return pTB->ImplGetToolBoxPrivateData()->maDisplayBackground;
3079 if( !IsBackground() )
3081 if( mpWindowImpl->mpParent )
3082 return mpWindowImpl->mpParent->GetDisplayBackground();
3085 const Wallpaper& rBack = GetBackground();
3086 if( ! rBack.IsBitmap() &&
3087 ! rBack.IsGradient() &&
3088 rBack.GetColor()== COL_TRANSPARENT &&
3089 mpWindowImpl->mpParent )
3090 return mpWindowImpl->mpParent->GetDisplayBackground();
3091 return rBack;
3094 const OUString& Window::GetHelpText() const
3096 OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
3097 bool bStrHelpId = !aStrHelpId.isEmpty();
3099 if ( !mpWindowImpl->maHelpText.getLength() && bStrHelpId )
3101 if ( !IsDialog() && (mpWindowImpl->mnType != WindowType::TABPAGE) && (mpWindowImpl->mnType != WindowType::FLOATINGWINDOW) )
3103 Help* pHelp = Application::GetHelp();
3104 if ( pHelp )
3106 mpWindowImpl->maHelpText = pHelp->GetHelpText(aStrHelpId, this);
3107 mpWindowImpl->mbHelpTextDynamic = false;
3111 else if( mpWindowImpl->mbHelpTextDynamic && bStrHelpId )
3113 static const char* pEnv = getenv( "HELP_DEBUG" );
3114 if( pEnv && *pEnv )
3116 OUString aTxt = mpWindowImpl->maHelpText + "\n------------------\n" + aStrHelpId;
3117 mpWindowImpl->maHelpText = aTxt;
3119 mpWindowImpl->mbHelpTextDynamic = false;
3122 //Fallback to Window::GetAccessibleDescription without reentry to GetHelpText()
3123 if (mpWindowImpl->maHelpText.isEmpty() && mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleDescription)
3124 return *mpWindowImpl->mpAccessibleInfos->pAccessibleDescription;
3125 return mpWindowImpl->maHelpText;
3128 void Window::SetWindowPeer( Reference< css::awt::XWindowPeer > const & xPeer, VCLXWindow* pVCLXWindow )
3130 if (!mpWindowImpl)
3131 return;
3133 // be safe against re-entrance: first clear the old ref, then assign the new one
3134 mpWindowImpl->mxWindowPeer.clear();
3135 mpWindowImpl->mxWindowPeer = xPeer;
3137 mpWindowImpl->mpVCLXWindow = pVCLXWindow;
3140 Reference< css::awt::XWindowPeer > Window::GetComponentInterface( bool bCreate )
3142 if ( !mpWindowImpl->mxWindowPeer.is() && bCreate )
3144 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
3145 if ( pWrapper )
3146 mpWindowImpl->mxWindowPeer = pWrapper->GetWindowInterface( this );
3148 return mpWindowImpl->mxWindowPeer;
3151 void Window::SetComponentInterface( Reference< css::awt::XWindowPeer > const & xIFace )
3153 UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
3154 SAL_WARN_IF( !pWrapper, "vcl.window", "SetComponentInterface: No Wrapper!" );
3155 if ( pWrapper )
3156 pWrapper->SetWindowInterface( this, xIFace );
3159 typedef std::map<vcl::LOKWindowId, VclPtr<vcl::Window>> LOKWindowsMap;
3161 namespace {
3163 LOKWindowsMap& GetLOKWindowsMap()
3165 // never use this in the desktop case
3166 assert(comphelper::LibreOfficeKit::isActive());
3168 // Map to remember the LOKWindowId <-> Window binding.
3169 static LOKWindowsMap s_aLOKWindowsMap;
3171 return s_aLOKWindowsMap;
3176 void Window::SetLOKNotifier(const vcl::ILibreOfficeKitNotifier* pNotifier, bool bParent)
3178 // don't allow setting this twice
3179 assert(mpWindowImpl->mpLOKNotifier == nullptr);
3180 assert(pNotifier);
3181 // never use this in the desktop case
3182 assert(comphelper::LibreOfficeKit::isActive());
3184 if (!bParent)
3186 // Counter to be able to have unique id's for each window.
3187 static vcl::LOKWindowId sLastLOKWindowId = 1;
3189 // assign the LOK window id
3190 assert(mpWindowImpl->mnLOKWindowId == 0);
3191 mpWindowImpl->mnLOKWindowId = sLastLOKWindowId++;
3192 GetLOKWindowsMap().insert(std::map<vcl::LOKWindowId, VclPtr<vcl::Window>>::value_type(mpWindowImpl->mnLOKWindowId, this));
3194 else
3195 mpWindowImpl->mbLOKParentNotifier = true;
3197 mpWindowImpl->mpLOKNotifier = pNotifier;
3200 VclPtr<Window> Window::FindLOKWindow(vcl::LOKWindowId nWindowId)
3202 const auto it = GetLOKWindowsMap().find(nWindowId);
3203 if (it != GetLOKWindowsMap().end())
3204 return it->second;
3206 return VclPtr<Window>();
3209 void Window::ReleaseLOKNotifier()
3211 // unregister the LOK window binding
3212 if (mpWindowImpl->mnLOKWindowId > 0)
3213 GetLOKWindowsMap().erase(mpWindowImpl->mnLOKWindowId);
3215 mpWindowImpl->mpLOKNotifier = nullptr;
3216 mpWindowImpl->mnLOKWindowId = 0;
3219 ILibreOfficeKitNotifier::~ILibreOfficeKitNotifier()
3221 if (!comphelper::LibreOfficeKit::isActive())
3223 return;
3226 for (auto it = GetLOKWindowsMap().begin(); it != GetLOKWindowsMap().end();)
3228 WindowImpl* pWindowImpl = it->second->ImplGetWindowImpl();
3229 if (pWindowImpl && pWindowImpl->mpLOKNotifier == this)
3231 pWindowImpl->mpLOKNotifier = nullptr;
3232 pWindowImpl->mnLOKWindowId = 0;
3233 it = GetLOKWindowsMap().erase(it);
3234 continue;
3237 ++it;
3241 const vcl::ILibreOfficeKitNotifier* Window::GetLOKNotifier() const
3243 return mpWindowImpl->mpLOKNotifier;
3246 vcl::LOKWindowId Window::GetLOKWindowId() const
3248 return mpWindowImpl->mnLOKWindowId;
3251 VclPtr<vcl::Window> Window::GetParentWithLOKNotifier()
3253 VclPtr<vcl::Window> pWindow(this);
3255 while (pWindow && !pWindow->GetLOKNotifier())
3256 pWindow = pWindow->GetParent();
3258 return pWindow;
3261 namespace
3264 const char* windowTypeName(WindowType nWindowType)
3266 switch (nWindowType)
3268 case WindowType::NONE: return "none";
3269 case WindowType::MESSBOX: return "messagebox";
3270 case WindowType::INFOBOX: return "infobox";
3271 case WindowType::WARNINGBOX: return "warningbox";
3272 case WindowType::ERRORBOX: return "errorbox";
3273 case WindowType::QUERYBOX: return "querybox";
3274 case WindowType::WINDOW: return "window";
3275 case WindowType::WORKWINDOW: return "workwindow";
3276 case WindowType::CONTAINER: return "container";
3277 case WindowType::FLOATINGWINDOW: return "floatingwindow";
3278 case WindowType::DIALOG: return "dialog";
3279 case WindowType::MODELESSDIALOG: return "modelessdialog";
3280 case WindowType::MODALDIALOG: return "modaldialog";
3281 case WindowType::CONTROL: return "control";
3282 case WindowType::PUSHBUTTON: return "pushbutton";
3283 case WindowType::OKBUTTON: return "okbutton";
3284 case WindowType::CANCELBUTTON: return "cancelbutton";
3285 case WindowType::HELPBUTTON: return "helpbutton";
3286 case WindowType::IMAGEBUTTON: return "imagebutton";
3287 case WindowType::MENUBUTTON: return "menubutton";
3288 case WindowType::MOREBUTTON: return "morebutton";
3289 case WindowType::SPINBUTTON: return "spinbutton";
3290 case WindowType::RADIOBUTTON: return "radiobutton";
3291 case WindowType::CHECKBOX: return "checkbox";
3292 case WindowType::TRISTATEBOX: return "tristatebox";
3293 case WindowType::EDIT: return "edit";
3294 case WindowType::MULTILINEEDIT: return "multilineedit";
3295 case WindowType::COMBOBOX: return "combobox";
3296 case WindowType::LISTBOX: return "listbox";
3297 case WindowType::MULTILISTBOX: return "multilistbox";
3298 case WindowType::FIXEDTEXT: return "fixedtext";
3299 case WindowType::FIXEDLINE: return "fixedline";
3300 case WindowType::FIXEDBITMAP: return "fixedbitmap";
3301 case WindowType::FIXEDIMAGE: return "fixedimage";
3302 case WindowType::GROUPBOX: return "groupbox";
3303 case WindowType::SCROLLBAR: return "scrollbar";
3304 case WindowType::SCROLLBARBOX: return "scrollbarbox";
3305 case WindowType::SPLITTER: return "splitter";
3306 case WindowType::SPLITWINDOW: return "splitwindow";
3307 case WindowType::SPINFIELD: return "spinfield";
3308 case WindowType::PATTERNFIELD: return "patternfield";
3309 case WindowType::NUMERICFIELD: return "numericfield";
3310 case WindowType::METRICFIELD: return "metricfield";
3311 case WindowType::CURRENCYFIELD: return "currencyfield";
3312 case WindowType::DATEFIELD: return "datefield";
3313 case WindowType::TIMEFIELD: return "timefield";
3314 case WindowType::PATTERNBOX: return "patternbox";
3315 case WindowType::NUMERICBOX: return "numericbox";
3316 case WindowType::METRICBOX: return "metricbox";
3317 case WindowType::CURRENCYBOX: return "currencybox";
3318 case WindowType::DATEBOX: return "datebox";
3319 case WindowType::TIMEBOX: return "timebox";
3320 case WindowType::LONGCURRENCYFIELD: return "longcurrencyfield";
3321 case WindowType::LONGCURRENCYBOX: return "longcurrencybox";
3322 case WindowType::SCROLLWINDOW: return "scrollwindow";
3323 case WindowType::TOOLBOX: return "toolbox";
3324 case WindowType::DOCKINGWINDOW: return "dockingwindow";
3325 case WindowType::STATUSBAR: return "statusbar";
3326 case WindowType::TABPAGE: return "tabpage";
3327 case WindowType::TABCONTROL: return "tabcontrol";
3328 case WindowType::TABDIALOG: return "tabdialog";
3329 case WindowType::BORDERWINDOW: return "borderwindow";
3330 case WindowType::BUTTONDIALOG: return "buttondialog";
3331 case WindowType::SYSTEMCHILDWINDOW: return "systemchildwindow";
3332 case WindowType::SLIDER: return "slider";
3333 case WindowType::MENUBARWINDOW: return "menubarwindow";
3334 case WindowType::TREELISTBOX: return "treelistbox";
3335 case WindowType::HELPTEXTWINDOW: return "helptextwindow";
3336 case WindowType::INTROWINDOW: return "introwindow";
3337 case WindowType::LISTBOXWINDOW: return "listboxwindow";
3338 case WindowType::DOCKINGAREA: return "dockingarea";
3339 case WindowType::RULER: return "ruler";
3340 case WindowType::CALCINPUTLINE: return "calcinputline";
3341 case WindowType::HEADERBAR: return "headerbar";
3342 case WindowType::VERTICALTABCONTROL: return "verticaltabcontrol";
3344 // nothing to do here, but for completeness
3345 case WindowType::TOOLKIT_FRAMEWINDOW: return "toolkit_framewindow";
3346 case WindowType::TOOLKIT_SYSTEMCHILDWINDOW: return "toolkit_systemchildwindow";
3349 return "none";
3354 boost::property_tree::ptree Window::DumpAsPropertyTree()
3356 boost::property_tree::ptree aTree;
3357 aTree.put("id", get_id()); // TODO could be missing - sort out
3358 aTree.put("type", windowTypeName(GetType()));
3359 aTree.put("text", GetText());
3360 aTree.put("enabled", IsEnabled());
3362 boost::property_tree::ptree aChildren;
3363 if (vcl::Window* pChild = mpWindowImpl->mpFirstChild)
3365 while (pChild)
3367 if (pChild->IsVisible()) {
3368 boost::property_tree::ptree aSubTree = pChild->DumpAsPropertyTree();
3369 int nLeft = pChild->get_grid_left_attach();
3370 int nTop = pChild->get_grid_top_attach();
3371 if (nLeft != -1 && nTop != -1)
3373 OUString sLeft = OUString::number(nLeft);
3374 OUString sTop = OUString::number(nTop);
3375 aSubTree.put("left", sLeft);
3376 aSubTree.put("top", sTop);
3378 aChildren.push_back(std::make_pair("", aSubTree));
3380 pChild = pChild->mpWindowImpl->mpNext;
3382 aTree.add_child("children", aChildren);
3385 return aTree;
3388 void Window::ImplCallDeactivateListeners( vcl::Window *pNew )
3390 // no deactivation if the newly activated window is my child
3391 if ( !pNew || !ImplIsChild( pNew ) )
3393 VclPtr<vcl::Window> xWindow(this);
3394 CallEventListeners( VclEventId::WindowDeactivate, pNew );
3395 if( xWindow->IsDisposed() )
3396 return;
3398 // #100759#, avoid walking the wrong frame's hierarchy
3399 // eg, undocked docking windows (ImplDockFloatWin)
3400 if ( ImplGetParent() && mpWindowImpl->mpFrameWindow == ImplGetParent()->mpWindowImpl->mpFrameWindow )
3401 ImplGetParent()->ImplCallDeactivateListeners( pNew );
3405 void Window::ImplCallActivateListeners( vcl::Window *pOld )
3407 // no activation if the old active window is my child
3408 if ( !pOld || !ImplIsChild( pOld ) )
3410 VclPtr<vcl::Window> xWindow(this);
3411 CallEventListeners( VclEventId::WindowActivate, pOld );
3412 if( xWindow->IsDisposed() )
3413 return;
3415 if ( ImplGetParent() )
3416 ImplGetParent()->ImplCallActivateListeners( pOld );
3417 else if( (mpWindowImpl->mnStyle & WB_INTROWIN) == 0 )
3419 // top level frame reached: store hint for DefModalDialogParent
3420 ImplGetSVData()->maWinData.mpActiveApplicationFrame = mpWindowImpl->mpFrameWindow;
3425 void Window::SetClipboard(Reference<XClipboard> const & xClipboard)
3427 if (mpWindowImpl->mpFrameData)
3428 mpWindowImpl->mpFrameData->mxClipboard = xClipboard;
3431 Reference< XClipboard > Window::GetClipboard()
3433 if (!mpWindowImpl->mpFrameData)
3434 return static_cast<XClipboard*>(nullptr);
3435 if (!mpWindowImpl->mpFrameData->mxClipboard.is())
3436 mpWindowImpl->mpFrameData->mxClipboard = GetSystemClipboard();
3437 return mpWindowImpl->mpFrameData->mxClipboard;
3440 Reference< XClipboard > Window::GetPrimarySelection()
3442 if (!mpWindowImpl->mpFrameData)
3443 return static_cast<XClipboard*>(nullptr);
3444 if (!mpWindowImpl->mpFrameData->mxSelection.is())
3445 mpWindowImpl->mpFrameData->mxSelection = GetSystemPrimarySelection();
3446 return mpWindowImpl->mpFrameData->mxSelection;
3449 void Window::RecordLayoutData( vcl::ControlLayoutData* pLayout, const tools::Rectangle& rRect )
3451 assert(mpOutDevData);
3452 mpOutDevData->mpRecordLayout = pLayout;
3453 mpOutDevData->maRecordRect = rRect;
3454 Paint(*this, rRect);
3455 mpOutDevData->mpRecordLayout = nullptr;
3458 void Window::DrawSelectionBackground( const tools::Rectangle& rRect,
3459 sal_uInt16 highlight,
3460 bool bChecked,
3461 bool bDrawBorder
3464 if( rRect.IsEmpty() )
3465 return;
3467 const StyleSettings& rStyles = GetSettings().GetStyleSettings();
3469 // colors used for item highlighting
3470 Color aSelectionBorderCol( rStyles.GetHighlightColor() );
3471 Color aSelectionFillCol( aSelectionBorderCol );
3473 bool bDark = rStyles.GetFaceColor().IsDark();
3474 bool bBright = ( rStyles.GetFaceColor() == COL_WHITE );
3476 int c1 = aSelectionBorderCol.GetLuminance();
3477 int c2 = GetBackgroundColor().GetLuminance();
3479 if( !bDark && !bBright && abs( c2-c1 ) < 75 )
3481 // contrast too low
3482 sal_uInt16 h,s,b;
3483 aSelectionFillCol.RGBtoHSB( h, s, b );
3484 if( b > 50 ) b -= 40;
3485 else b += 40;
3486 aSelectionFillCol = Color::HSBtoRGB( h, s, b );
3487 aSelectionBorderCol = aSelectionFillCol;
3490 tools::Rectangle aRect( rRect );
3491 Color oldFillCol = GetFillColor();
3492 Color oldLineCol = GetLineColor();
3494 if( bDrawBorder )
3495 SetLineColor( bDark ? COL_WHITE : ( bBright ? COL_BLACK : aSelectionBorderCol ) );
3496 else
3497 SetLineColor();
3499 sal_uInt16 nPercent = 0;
3500 if( !highlight )
3502 if( bDark )
3503 aSelectionFillCol = COL_BLACK;
3504 else
3505 nPercent = 80; // just checked (light)
3507 else
3509 if( bChecked && highlight == 2 )
3511 if( bDark )
3512 aSelectionFillCol = COL_LIGHTGRAY;
3513 else if ( bBright )
3515 aSelectionFillCol = COL_BLACK;
3516 SetLineColor( COL_BLACK );
3517 nPercent = 0;
3519 else
3520 nPercent = 20; // selected, pressed or checked ( very dark )
3522 else if( bChecked || highlight == 1 )
3524 if( bDark )
3525 aSelectionFillCol = COL_GRAY;
3526 else if ( bBright )
3528 aSelectionFillCol = COL_BLACK;
3529 SetLineColor( COL_BLACK );
3530 nPercent = 0;
3532 else
3533 nPercent = 35; // selected, pressed or checked ( very dark )
3535 else
3537 if( bDark )
3538 aSelectionFillCol = COL_LIGHTGRAY;
3539 else if ( bBright )
3541 aSelectionFillCol = COL_BLACK;
3542 SetLineColor( COL_BLACK );
3543 if( highlight == 3 )
3544 nPercent = 80;
3545 else
3546 nPercent = 0;
3548 else
3549 nPercent = 70; // selected ( dark )
3553 SetFillColor( aSelectionFillCol );
3555 if( bDark )
3557 DrawRect( aRect );
3559 else
3561 tools::Polygon aPoly( aRect );
3562 tools::PolyPolygon aPolyPoly( aPoly );
3563 DrawTransparent( aPolyPoly, nPercent );
3566 SetFillColor( oldFillCol );
3567 SetLineColor( oldLineCol );
3570 bool Window::IsScrollable() const
3572 // check for scrollbars
3573 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
3574 while( pChild )
3576 if( pChild->GetType() == WindowType::SCROLLBAR )
3577 return true;
3578 else
3579 pChild = pChild->mpWindowImpl->mpNext;
3581 return false;
3584 void Window::ImplMirrorFramePos( Point &pt ) const
3586 pt.setX( mpWindowImpl->mpFrame->maGeometry.nWidth-1-pt.X() );
3589 // frame based modal counter (dialogs are not modal to the whole application anymore)
3590 bool Window::IsInModalMode() const
3592 return (mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mnModalMode != 0);
3595 void Window::IncModalCount()
3597 vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
3598 vcl::Window* pParent = pFrameWindow;
3599 while( pFrameWindow )
3601 pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode++;
3602 while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
3604 pParent = pParent->GetParent();
3606 pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
3609 void Window::DecModalCount()
3611 vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
3612 vcl::Window* pParent = pFrameWindow;
3613 while( pFrameWindow )
3615 pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode--;
3616 while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
3618 pParent = pParent->GetParent();
3620 pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
3624 void Window::ImplIsInTaskPaneList( bool mbIsInTaskList )
3626 mpWindowImpl->mbIsInTaskPaneList = mbIsInTaskList;
3629 void Window::ImplNotifyIconifiedState( bool bIconified )
3631 mpWindowImpl->mpFrameWindow->CallEventListeners( bIconified ? VclEventId::WindowMinimize : VclEventId::WindowNormalize );
3632 // #109206# notify client window as well to have toolkit topwindow listeners notified
3633 if( mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow && mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow )
3634 mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow->CallEventListeners( bIconified ? VclEventId::WindowMinimize : VclEventId::WindowNormalize );
3637 bool Window::HasActiveChildFrame() const
3639 bool bRet = false;
3640 vcl::Window *pFrameWin = ImplGetSVData()->maWinData.mpFirstFrame;
3641 while( pFrameWin )
3643 if( pFrameWin != mpWindowImpl->mpFrameWindow )
3645 bool bDecorated = false;
3646 VclPtr< vcl::Window > pChildFrame = pFrameWin->ImplGetWindow();
3647 // #i15285# unfortunately WB_MOVEABLE is the same as WB_TABSTOP which can
3648 // be removed for ToolBoxes to influence the keyboard accessibility
3649 // thus WB_MOVEABLE is no indicator for decoration anymore
3650 // but FloatingWindows carry this information in their TitleType...
3651 // TODO: avoid duplicate WinBits !!!
3652 if( pChildFrame && pChildFrame->ImplIsFloatingWindow() )
3653 bDecorated = static_cast<FloatingWindow*>(pChildFrame.get())->GetTitleType() != FloatWinTitleType::NONE;
3654 if( bDecorated || (pFrameWin->mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) ) )
3655 if( pChildFrame && pChildFrame->IsVisible() && pChildFrame->IsActive() )
3657 if( ImplIsChild( pChildFrame, true ) )
3659 bRet = true;
3660 break;
3664 pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
3666 return bRet;
3669 LanguageType Window::GetInputLanguage() const
3671 return mpWindowImpl->mpFrame->GetInputLanguage();
3674 void Window::EnableNativeWidget( bool bEnable )
3676 static const char* pNoNWF = getenv( "SAL_NO_NWF" );
3677 if( pNoNWF && *pNoNWF )
3678 bEnable = false;
3680 if( bEnable != ImplGetWinData()->mbEnableNativeWidget )
3682 ImplGetWinData()->mbEnableNativeWidget = bEnable;
3684 // send datachanged event to allow for internal changes required for NWF
3685 // like clipmode, transparency, etc.
3686 DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, mxSettings.get(), AllSettingsFlags::STYLE );
3687 CompatDataChanged( aDCEvt );
3689 // sometimes the borderwindow is queried, so keep it in sync
3690 if( mpWindowImpl->mpBorderWindow )
3691 mpWindowImpl->mpBorderWindow->ImplGetWinData()->mbEnableNativeWidget = bEnable;
3694 // push down, useful for compound controls
3695 VclPtr< vcl::Window > pChild = mpWindowImpl->mpFirstChild;
3696 while( pChild )
3698 pChild->EnableNativeWidget( bEnable );
3699 pChild = pChild->mpWindowImpl->mpNext;
3703 bool Window::IsNativeWidgetEnabled() const
3705 return ImplGetWinData()->mbEnableNativeWidget;
3708 Reference< css::rendering::XCanvas > Window::ImplGetCanvas( bool bSpriteCanvas ) const
3710 // try to retrieve hard reference from weak member
3711 Reference< css::rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
3713 // canvas still valid? Then we're done.
3714 if( xCanvas.is() )
3715 return xCanvas;
3717 Sequence< Any > aArg(5);
3719 // Feed any with operating system's window handle
3721 // common: first any is VCL pointer to window (for VCL canvas)
3722 aArg[ 0 ] <<= reinterpret_cast<sal_Int64>(this);
3723 aArg[ 1 ] <<= css::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
3724 aArg[ 2 ] <<= mpWindowImpl->mbAlwaysOnTop;
3725 aArg[ 3 ] <<= Reference< css::awt::XWindow >(
3726 const_cast<vcl::Window*>(this)->GetComponentInterface(),
3727 UNO_QUERY );
3728 aArg[ 4 ] = GetSystemGfxDataAny();
3730 Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
3732 // Create canvas instance with window handle
3734 static vcl::DeleteUnoReferenceOnDeinit<XMultiComponentFactory> xStaticCanvasFactory(
3735 css::rendering::CanvasFactory::create( xContext ) );
3736 Reference<XMultiComponentFactory> xCanvasFactory(xStaticCanvasFactory.get());
3738 if(xCanvasFactory.is())
3740 #ifdef _WIN32
3741 // see #140456# - if we're running on a multiscreen setup,
3742 // request special, multi-screen safe sprite canvas
3743 // implementation (not DX5 canvas, as it cannot cope with
3744 // surfaces spanning multiple displays). Note: canvas
3745 // (without sprite) stays the same)
3746 const sal_uInt32 nDisplay = static_cast< WinSalFrame* >( mpWindowImpl->mpFrame )->mnDisplay;
3747 if( nDisplay >= Application::GetScreenCount() )
3749 xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
3750 bSpriteCanvas ?
3751 OUString( "com.sun.star.rendering.SpriteCanvas.MultiScreen" ) :
3752 OUString( "com.sun.star.rendering.Canvas.MultiScreen" ),
3753 aArg,
3754 xContext ),
3755 UNO_QUERY );
3758 else
3759 #endif
3761 xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
3762 bSpriteCanvas ?
3763 OUString( "com.sun.star.rendering.SpriteCanvas" ) :
3764 OUString( "com.sun.star.rendering.Canvas" ),
3765 aArg,
3766 xContext ),
3767 UNO_QUERY );
3770 mpWindowImpl->mxCanvas = xCanvas;
3773 // no factory??? Empty reference, then.
3774 return xCanvas;
3777 Reference< css::rendering::XCanvas > Window::GetCanvas() const
3779 return ImplGetCanvas( false );
3782 Reference< css::rendering::XSpriteCanvas > Window::GetSpriteCanvas() const
3784 Reference< css::rendering::XSpriteCanvas > xSpriteCanvas(
3785 ImplGetCanvas( true ), UNO_QUERY );
3786 return xSpriteCanvas;
3789 OUString Window::GetSurroundingText() const
3791 return OUString();
3794 Selection Window::GetSurroundingTextSelection() const
3796 return Selection( 0, 0 );
3799 bool Window::UsePolyPolygonForComplexGradient()
3801 return meRasterOp != RasterOp::OverPaint;
3804 void Window::ApplySettings(vcl::RenderContext& /*rRenderContext*/)
3808 const SystemEnvData* Window::GetSystemData() const
3811 return mpWindowImpl->mpFrame ? mpWindowImpl->mpFrame->GetSystemData() : nullptr;
3814 bool Window::SupportsDoubleBuffering() const
3816 return mpWindowImpl->mpFrameData->mpBuffer;
3819 void Window::RequestDoubleBuffering(bool bRequest)
3821 if (bRequest)
3823 mpWindowImpl->mpFrameData->mpBuffer = VclPtrInstance<VirtualDevice>();
3824 // Make sure that the buffer size matches the frame size.
3825 mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(mpWindowImpl->mpFrameWindow->GetOutputSizePixel());
3827 else
3828 mpWindowImpl->mpFrameData->mpBuffer.reset();
3832 * The rational here is that we moved destructors to
3833 * dispose and this altered a lot of code paths, that
3834 * are better left unchanged for now.
3836 #define COMPAT_BODY(method,args) \
3837 if (!mpWindowImpl || mpWindowImpl->mbInDispose) \
3838 Window::method args; \
3839 else \
3840 method args;
3842 void Window::CompatGetFocus()
3844 COMPAT_BODY(GetFocus,())
3847 void Window::CompatLoseFocus()
3849 COMPAT_BODY(LoseFocus,())
3852 void Window::CompatStateChanged( StateChangedType nStateChange )
3854 COMPAT_BODY(StateChanged,(nStateChange))
3857 void Window::CompatDataChanged( const DataChangedEvent& rDCEvt )
3859 COMPAT_BODY(DataChanged,(rDCEvt))
3862 bool Window::CompatPreNotify( NotifyEvent& rNEvt )
3864 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3865 return Window::PreNotify( rNEvt );
3866 else
3867 return PreNotify( rNEvt );
3870 bool Window::CompatNotify( NotifyEvent& rNEvt )
3872 if (!mpWindowImpl || mpWindowImpl->mbInDispose)
3873 return Window::EventNotify( rNEvt );
3874 else
3875 return EventNotify( rNEvt );
3878 void Window::set_id(const OUString& rID)
3880 mpWindowImpl->maID = rID;
3883 const OUString& Window::get_id() const
3885 return mpWindowImpl->maID;
3888 FactoryFunction Window::GetUITestFactory() const
3890 return WindowUIObject::create;
3893 } /* namespace vcl */
3895 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */