/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
Window::Window( WindowType eType )
: mpWindowImpl(new WindowImpl( *this, eType ))
{ // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
mpWindowImpl->mxOutDev->mbEnableRTL = AllSettings::GetLayoutRTL();
}
Window::Window( vcl::Window* pParent, WinBits nStyle )
: mpWindowImpl(new WindowImpl( *this, WindowType::WINDOW ))
{ // true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
mpWindowImpl->mxOutDev->mbEnableRTL = AllSettings::GetLayoutRTL();
ImplInit( pParent, nStyle, nullptr );
}
#if OSL_DEBUG_LEVEL > 0 namespace
{
OString lcl_createWindowInfo(const vcl::Window* pWindow)
{ // skip border windows, they do not carry information that // would help with diagnosing the problem const vcl::Window* pTempWin( pWindow ); while ( pTempWin && pTempWin->GetType() == WindowType::BORDERWINDOW ) {
pTempWin = pTempWin->GetWindow( GetWindowType::FirstChild );
} // check if pTempWin is not null, otherwise use the // original address if ( pTempWin ) {
pWindow = pTempWin;
}
void Window::dispose()
{
assert( mpWindowImpl );
assert( !mpWindowImpl->mbInDispose ); // should only be called from disposeOnce()
assert( (!mpWindowImpl->mpParent ||
mpWindowImpl->mpParent->mpWindowImpl) && "vcl::Window child should have its parent disposed first" );
// remove Key and Mouse events issued by Application::PostKey/MouseEvent
Application::RemoveMouseAndKeyEvents( this );
// Dispose of the canvas implementation (which, currently, has an // own wrapper window as a child to this one.
GetOutDev()->ImplDisposeCanvas();
mpWindowImpl->mbInDispose = true;
CallEventListeners( VclEventId::ObjectDying );
// do not send child events for frames that were registered as native frames if( !IsNativeFrame() && mpWindowImpl->mbReallyVisible ) if ( ImplIsAccessibleCandidate() && GetAccessibleParentWindow() )
GetAccessibleParentWindow()->CallEventListeners( VclEventId::WindowChildDestroyed, this );
// remove associated data structures from dockingmanager
ImplGetDockingManager()->RemoveWindow( this );
// remove ownerdraw decorated windows from list in the top-most frame window if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
{
::std::vector< VclPtr<vcl::Window> >& rList = ImplGetOwnerDrawList(); auto p = ::std::find( rList.begin(), rList.end(), VclPtr<vcl::Window>(this) ); if( p != rList.end() )
rList.erase( p );
}
// shutdown drag and drop if( mpWindowImpl->mxDNDListenerContainer.is() )
mpWindowImpl->mxDNDListenerContainer->dispose();
// shutdown drag and drop for this frame window
Reference< XComponent > xComponent( mpWindowImpl->mpFrameData->mxDropTarget, UNO_QUERY );
// DNDEventDispatcher does not hold a reference of the DropTarget, // so it's ok if it does not support XComponent if( xComponent.is() )
xComponent->dispose();
} catch (const Exception&)
{ // can be safely ignored here.
}
}
UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper( false ); if ( pWrapper )
pWrapper->WindowDestroyed( this );
// MT: Must be called after WindowDestroyed! // Otherwise, if the accessible is a VCLXWindow, it will try to destroy this window again! // But accessibility implementations from applications need this dispose. if ( mpWindowImpl->mxAccessible.is() )
{
Reference< XComponent> xC( mpWindowImpl->mxAccessible, UNO_QUERY ); if ( xC.is() )
xC->dispose();
mpWindowImpl->mxAccessible.clear();
}
if (mpWindowImpl->mpAccessibleInfos)
mpWindowImpl->mpAccessibleInfos->xAccessibleParent.clear();
SAL_WARN_IF(pSVData->mpWinData->mpTrackWin.get() == this, "vcl.window", "Window::~Window(): Window is in TrackingMode");
SAL_WARN_IF(IsMouseCaptured(), "vcl.window", "Window::~Window(): Window has the mouse captured");
// due to old compatibility if (pSVData->mpWinData->mpTrackWin == this)
EndTracking(); if (IsMouseCaptured())
ReleaseMouse();
// hide window in order to trigger the Paint-Handling
Hide();
// EndExtTextInputMode if (pSVData->mpWinData->mpExtTextInputWin == this)
{
EndExtTextInput(); if (pSVData->mpWinData->mpExtTextInputWin == this)
pSVData->mpWinData->mpExtTextInputWin = nullptr;
}
// check if the focus window is our child bool bHasFocusedChild = false; if (pSVData->mpWinData->mpFocusWin && ImplIsRealParentPath(pSVData->mpWinData->mpFocusWin))
{ // #122232#, this must not happen and is an application bug ! but we try some cleanup to hopefully avoid crashes, see below
bHasFocusedChild = true; #if OSL_DEBUG_LEVEL > 0
OUString aTempStr = "Window (" + GetText() + ") with focused child window destroyed ! THIS WILL LEAD TO CRASHES AND MUST BE FIXED !";
SAL_WARN( "vcl", aTempStr );
Application::Abort(aTempStr); #endif
}
// if we get focus pass focus to another window
vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow(); if (pSVData->mpWinData->mpFocusWin == this
|| bHasFocusedChild) // #122232#, see above, try some cleanup
{ if ( mpWindowImpl->mbFrame )
{
pSVData->mpWinData->mpFocusWin = nullptr;
pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
} else
{
vcl::Window* pParent = GetParent();
vcl::Window* pBorderWindow = mpWindowImpl->mpBorderWindow; // when windows overlap, give focus to the parent // of the next FrameWindow if ( pBorderWindow )
{ if ( pBorderWindow->ImplIsOverlapWindow() )
pParent = pBorderWindow->mpWindowImpl->mpOverlapWindow;
} elseif ( ImplIsOverlapWindow() )
pParent = mpWindowImpl->mpOverlapWindow;
// If the focus was set back to 'this' set it to nothing if (pSVData->mpWinData->mpFocusWin == this)
{
pSVData->mpWinData->mpFocusWin = nullptr;
pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
}
}
}
if ( pOverlapWindow != nullptr &&
pOverlapWindow->mpWindowImpl->mpLastFocusWindow == this )
pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
// reset hint for DefModalDialogParent if( pSVData->maFrameData.mpActiveApplicationFrame == this )
pSVData->maFrameData.mpActiveApplicationFrame = nullptr;
// reset hint of what was the last wheeled window if (pSVData->mpWinData->mpLastWheelWindow == this)
pSVData->mpWinData->mpLastWheelWindow = nullptr;
// reset marked windows if ( mpWindowImpl->mpFrameData != nullptr )
{ if ( mpWindowImpl->mpFrameData->mpFocusWin == this )
mpWindowImpl->mpFrameData->mpFocusWin = nullptr; if ( mpWindowImpl->mpFrameData->mpMouseMoveWin == this )
mpWindowImpl->mpFrameData->mpMouseMoveWin = nullptr; if ( mpWindowImpl->mpFrameData->mpMouseDownWin == this )
mpWindowImpl->mpFrameData->mpMouseDownWin = nullptr;
}
// reset Deactivate-Window if (pSVData->mpWinData->mpLastDeacWin == this)
pSVData->mpWinData->mpLastDeacWin = nullptr;
if ( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
{ if ( mpWindowImpl->mpFrameData->mnFocusId )
Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnFocusId );
mpWindowImpl->mpFrameData->mnFocusId = nullptr; if ( mpWindowImpl->mpFrameData->mnMouseMoveId )
Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId );
mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
}
// remove window from the lists
ImplRemoveWindow( true );
// de-register as "top window child" at our parent, if necessary if ( mpWindowImpl->mbFrame )
{ bool bIsTopWindow
= mpWindowImpl->mpWinData && (mpWindowImpl->mpWinData->mnIsTopWindow == 1); if ( mpWindowImpl->mpRealParent && bIsTopWindow )
{
ImplWinData* pParentWinData = mpWindowImpl->mpRealParent->ImplGetWinData();
auto myPos = ::std::find( pParentWinData->maTopWindowChildren.begin(),
pParentWinData->maTopWindowChildren.end(), VclPtr<vcl::Window>(this) );
SAL_WARN_IF( myPos == pParentWinData->maTopWindowChildren.end(), "vcl.window", "Window::~Window: inconsistency in top window chain!" ); if ( myPos != pParentWinData->maTopWindowChildren.end() )
pParentWinData->maTopWindowChildren.erase( myPos );
}
}
mpWindowImpl->mpWinData.reset();
// remove BorderWindow or Frame window data
mpWindowImpl->mpBorderWindow.disposeAndClear(); if ( mpWindowImpl->mbFrame )
{ if ( pSVData->maFrameData.mpFirstFrame == this )
pSVData->maFrameData.mpFirstFrame = mpWindowImpl->mpFrameData->mpNextFrame; else
{
sal_Int32 nWindows = 0;
vcl::Window* pSysWin = pSVData->maFrameData.mpFirstFrame; while ( pSysWin && pSysWin->mpWindowImpl->mpFrameData->mpNextFrame.get() != this )
{
pSysWin = pSysWin->mpWindowImpl->mpFrameData->mpNextFrame;
nWindows++;
}
if ( pSysWin )
{
assert (mpWindowImpl->mpFrameData->mpNextFrame.get() != pSysWin);
pSysWin->mpWindowImpl->mpFrameData->mpNextFrame = mpWindowImpl->mpFrameData->mpNextFrame;
} else// if it is not in the list, we can't remove it.
SAL_WARN("vcl.window", "Window " << this << " marked as frame window, " "is missing from list of " << nWindows << " frames");
} if (mpWindowImpl->mpFrame) // otherwise exception during init
{
mpWindowImpl->mpFrame->SetCallback( nullptr, nullptr );
pSVData->mpDefInst->DestroyFrame( mpWindowImpl->mpFrame );
}
assert (mpWindowImpl->mpFrameData->mnFocusId == nullptr);
assert (mpWindowImpl->mpFrameData->mnMouseMoveId == nullptr);
if (mpWindowImpl->mxWindowPeer)
mpWindowImpl->mxWindowPeer->dispose();
// should be the last statements
mpWindowImpl.reset();
pOutDev.disposeAndClear(); // just to make loplugin:vclwidgets happy
VclReferenceBase::dispose();
}
Window::~Window()
{
disposeOnce();
}
// We will eventually being removing the inheritance of OutputDevice // from Window. It will be replaced with a transient relationship such // that the OutputDevice is only live for the scope of the Paint method. // In the meantime this can help move us towards a Window use an // OutputDevice, not being one.
mpGraphics = mxOwnerWindow->mpWindowImpl->mpFrame->AcquireGraphics(); // try harder if no wingraphics was available directly if ( !mpGraphics )
{ // find another output device in the same frame
vcl::WindowOutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics.get(); while ( pReleaseOutDev )
{ if ( pReleaseOutDev->mxOwnerWindow && pReleaseOutDev->mxOwnerWindow->mpWindowImpl->mpFrame == mxOwnerWindow->mpWindowImpl->mpFrame ) break;
pReleaseOutDev = static_cast<vcl::WindowOutputDevice*>(pReleaseOutDev->mpPrevGraphics.get());
}
if ( pReleaseOutDev )
{ // steal the wingraphics from the other outdev
mpGraphics = pReleaseOutDev->mpGraphics;
pReleaseOutDev->ReleaseGraphics( false );
} else
{ // if needed retry after releasing least recently used wingraphics while ( !mpGraphics )
{ if ( !pSVData->maGDIData.mpLastWinGraphics ) break;
pSVData->maGDIData.mpLastWinGraphics->ReleaseGraphics();
mpGraphics = mxOwnerWindow->mpWindowImpl->mpFrame->AcquireGraphics();
}
}
}
if ( mpGraphics )
{ // update global LRU list of wingraphics
mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics.get();
pSVData->maGDIData.mpFirstWinGraphics = const_cast<vcl::WindowOutputDevice*>(this); if ( mpNextGraphics )
mpNextGraphics->mpPrevGraphics = const_cast<vcl::WindowOutputDevice*>(this); if ( !pSVData->maGDIData.mpLastWinGraphics )
pSVData->maGDIData.mpLastWinGraphics = const_cast<vcl::WindowOutputDevice*>(this);
static sal_Int32 CountDPIScaleFactor(sal_Int32 nDPI)
{ #ifndef MACOSX // Setting of HiDPI is unfortunately all only a heuristic; and to add // insult to an injury, the system is constantly lying to us about // the DPI and whatnot // eg. fdo#77059 - set the value from which we do consider the // screen HiDPI to greater than 168 if (nDPI > 216) // 96 * 2 + 96 / 4 return 250; elseif (nDPI > 168) // 96 * 2 - 96 / 4 return 200; elseif (nDPI > 120) // 96 * 1.5 - 96 / 4 return 150; #else
(void)nDPI; #endif
switch (mpWindowImpl->meType)
{ case WindowType::DIALOG: case WindowType::TABDIALOG: case WindowType::MODELESSDIALOG: case WindowType::MESSBOX: case WindowType::INFOBOX: case WindowType::WARNINGBOX: case WindowType::ERRORBOX: case WindowType::QUERYBOX:
nFrameStyle |= SalFrameStyleFlags::DIALOG; break; default: break;
}
// tdf#144624 for the DefaultWindow, which is never visible, don't // create an icon for it so construction of a DefaultWindow cannot // trigger creation of a VirtualDevice which itself requires a // DefaultWindow to exist if( nStyle & WB_DEFAULTWIN )
nFrameStyle |= SalFrameStyleFlags::NOICON;
SalFrame* pParentFrame = nullptr; if ( pParent )
pParentFrame = pParent->mpWindowImpl->mpFrame;
SalFrame* pFrame; if ( pSystemParentData )
pFrame = pSVData->mpDefInst->CreateChildFrame( pSystemParentData, nFrameStyle | SalFrameStyleFlags::PLUG ); else
pFrame = pSVData->mpDefInst->CreateFrame( pParentFrame, nFrameStyle ); if ( !pFrame )
{ // do not abort but throw an exception, may be the current thread terminates anyway (plugin-scenario) throw RuntimeException(
u"Could not create system window!"_ustr,
Reference< XInterface >() );
}
pFrame->SetCallback( this, ImplWindowFrameProc );
// set window frame data
mpWindowImpl->mpFrameData = new ImplFrameData( this );
mpWindowImpl->mpFrame = pFrame;
mpWindowImpl->mpFrameWindow = this;
mpWindowImpl->mpOverlapWindow = this;
if (!(nStyle & WB_DEFAULTWIN) && mpWindowImpl->mbDoubleBufferingRequested)
RequestDoubleBuffering(true);
// init data
mpWindowImpl->mpRealParent = pRealParent;
// #99318: make sure fontcache and list is available before call to SetSettings
mpWindowImpl->mxOutDev->mxFontCollection = mpWindowImpl->mpFrameData->mxFontCollection;
mpWindowImpl->mxOutDev->mxFontCache = mpWindowImpl->mpFrameData->mxFontCache;
if ( mpWindowImpl->mbFrame )
{ if ( pParent )
{
mpWindowImpl->mpFrameData->mnDPIX = pParent->mpWindowImpl->mpFrameData->mnDPIX;
mpWindowImpl->mpFrameData->mnDPIY = pParent->mpWindowImpl->mpFrameData->mnDPIY;
} else
{ if (auto* pGraphics = GetOutDev()->GetGraphics())
{
pGraphics->GetResolution(mpWindowImpl->mpFrameData->mnDPIX,
mpWindowImpl->mpFrameData->mnDPIY);
}
}
// add ownerdraw decorated frame windows to list in the top-most frame window // so they can be hidden on lose focus if( nStyle & WB_OWNERDRAWDECORATION )
ImplGetOwnerDrawList().emplace_back(this );
// delay settings initialization until first "real" frame // this relies on the IntroWindow not needing any system settings if ( !pSVData->maAppData.mbSettingsInit &&
! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN))
)
{ // side effect: ImplUpdateGlobalSettings does an ImplGetFrame()->UpdateSettings
ImplUpdateGlobalSettings( *pSVData->maAppData.mxSettings );
mpWindowImpl->mxOutDev->SetSettings( *pSVData->maAppData.mxSettings );
pSVData->maAppData.mbSettingsInit = true;
}
// If we create a Window with default size, query this // size directly, because we want resize all Controls to // the correct size before we display the window if ( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_APP) )
mpWindowImpl->mpFrame->GetClientSize( mpWindowImpl->mxOutDev->mnOutWidth, mpWindowImpl->mxOutDev->mnOutHeight );
} else
{ if ( pParent )
{ if ( !ImplIsOverlapWindow() )
{
mpWindowImpl->mbDisabled = pParent->mpWindowImpl->mbDisabled;
mpWindowImpl->mbInputDisabled = pParent->mpWindowImpl->mbInputDisabled;
mpWindowImpl->meAlwaysInputMode = pParent->mpWindowImpl->meAlwaysInputMode;
}
if (!comphelper::IsFuzzing())
{ // we don't want to call the WindowOutputDevice override of this because // it calls back into us.
mpWindowImpl->mxOutDev->OutputDevice::SetSettings( pParent->GetSettings() );
}
}
}
// setup the scale factor for HiDPI displays
mpWindowImpl->mxOutDev->mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
mpWindowImpl->mxOutDev->mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
mpWindowImpl->mxOutDev->mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
// calculate app font res (except for the Intro Window or the default window) if ( mpWindowImpl->mbFrame && !pSVData->maGDIData.mnAppFontX && ! (nStyle & (WB_INTROWIN|WB_DEFAULTWIN)) )
ImplInitAppFontData( this );
}
void Window::ImplInitAppFontData( vcl::Window const * pWindow )
{
ImplSVData* pSVData = ImplGetSVData();
tools::Long nTextHeight = pWindow->GetTextHeight();
tools::Long nTextWidth = pWindow->approximate_char_width() * 8;
tools::Long nSymHeight = nTextHeight*4; // Make the basis wider if the font is too narrow // such that the dialog looks symmetrical and does not become too narrow. // Add some extra space when the dialog has the same width, // as a little more space is better. if ( nSymHeight > nTextWidth )
nTextWidth = nSymHeight; elseif ( nSymHeight+5 > nTextWidth )
nTextWidth = nSymHeight+5;
pSVData->maGDIData.mnAppFontX = nTextWidth * 10 / 8;
pSVData->maGDIData.mnAppFontY = nTextHeight * 10;
#ifdef MACOSX // FIXME: this is currently only on macOS, check with other // platforms if( pSVData->maNWFData.mbNoFocusRects )
{ // try to find out whether there is a large correction // of control sizes, if yes, make app font scalings larger // so dialog positioning is not completely off
ImplControlValue aControlValue;
tools::Rectangle aCtrlRegion( Point(), Size( nTextWidth < 10 ? 10 : nTextWidth, nTextHeight < 10 ? 10 : nTextHeight ) );
tools::Rectangle aBoundingRgn( aCtrlRegion );
tools::Rectangle aContentRgn( aCtrlRegion ); if( pWindow->GetNativeControlRegion( ControlType::Editbox, ControlPart::Entire, aCtrlRegion,
ControlState::ENABLED, aControlValue,
aBoundingRgn, aContentRgn ) )
{ // comment: the magical +6 is for the extra border in bordered // (which is the standard) edit fields if( aContentRgn.GetHeight() - nTextHeight > (nTextHeight+4)/4 )
pSVData->maGDIData.mnAppFontY = (aContentRgn.GetHeight()-4) * 10;
}
} #endif
}
const_cast<vcl::Window*>(this)->mpWindowImpl->mpWinData.reset(new ImplWinData);
mpWindowImpl->mpWinData->mbEnableNativeWidget = !(pNoNWF && *pNoNWF); // true: try to draw this control with native theme API
}
void Window::ImplSetReallyVisible()
{ // #i43594# it is possible that INITSHOW was never send, because the visibility state changed between // ImplCallInitShow() and ImplSetReallyVisible() when called from Show() // mbReallyShown is a useful indicator if( !mpWindowImpl->mbReallyShown )
ImplCallInitShow();
// the SHOW/HIDE events serve as indicators to send child creation/destroy events to the access bridge. // For this, the data member of the event must not be NULL. // Previously, we did this in Window::Show, but there some events got lost in certain situations. Now // we're doing it when the visibility really changes if( bBecameReallyVisible && ImplIsAccessibleCandidate() )
CallEventListeners( VclEventId::WindowShow, this ); // TODO. It's kind of a hack that we're re-using the VclEventId::WindowShow. Normally, we should // introduce another event which explicitly triggers the Accessibility implementations.
vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap; while ( pWindow )
{ if ( pWindow->mpWindowImpl->mbVisible )
pWindow->ImplSetReallyVisible();
pWindow = pWindow->mpWindowImpl->mpNext;
}
pWindow = mpWindowImpl->mpFirstChild; while ( pWindow )
{ if ( pWindow->mpWindowImpl->mbVisible )
pWindow->ImplSetReallyVisible();
pWindow = pWindow->mpWindowImpl->mpNext;
}
}
void Window::ImplInitResolutionSettings()
{ // recalculate AppFont-resolution and DPI-resolution if (mpWindowImpl->mbFrame)
{
GetOutDev()->mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
GetOutDev()->mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
// update the recalculated values for logical units // and also tools belonging to the values if (IsMapModeEnabled())
{
MapMode aMapMode = GetMapMode();
SetMapMode();
SetMapMode( aMapMode );
}
}
// #106948# always mirror our pos if our parent is not mirroring, even // if we are also not mirroring // RTL: check if parent is in different coordinates if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->GetOutDev()->ImplIsAntiparallel() )
{
nX = mpWindowImpl->mpParent->GetOutDev()->mnOutWidth - GetOutDev()->mnOutWidth - nX;
} /* #i99166# An LTR window in RTL UI that gets sized only would be expected to not moved its upper left point
*/ if( bnXRecycled )
{ if( GetOutDev()->ImplIsAntiparallel() )
{
aPtDev.setX( mpWindowImpl->mnAbsScreenX );
nOrgX = mpWindowImpl->maPos.X();
}
}
} elseif( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->GetOutDev()->ImplIsAntiparallel() )
{ // mirrored window in LTR UI
nX = mpWindowImpl->mpParent->GetOutDev()->mnOutWidth - GetOutDev()->mnOutWidth - nX;
}
// check maPos as well, as it could have been changed for client windows (ImplCallMove()) if ( mpWindowImpl->mnAbsScreenX != aPtDev.X() || nX != mpWindowImpl->mnX || nOrgX != mpWindowImpl->maPos.X() )
{ if ( bCopyBits && !pOverlapRegion )
{
pOverlapRegion.reset( new vcl::Region() );
ImplCalcOverlapRegion( GetOutputRectPixel(),
*pOverlapRegion, false, true );
}
mpWindowImpl->mnX = nX;
mpWindowImpl->maPos.setX( nOrgX );
mpWindowImpl->mnAbsScreenX = aPtDev.X();
bNewPos = true;
}
} if ( nFlags & PosSizeFlags::Y )
{ // check maPos as well, as it could have been changed for client windows (ImplCallMove()) if ( nY != mpWindowImpl->mnY || nY != mpWindowImpl->maPos.Y() )
{ if ( bCopyBits && !pOverlapRegion )
{
pOverlapRegion.reset( new vcl::Region() );
ImplCalcOverlapRegion( GetOutputRectPixel(),
*pOverlapRegion, false, true );
}
mpWindowImpl->mnY = nY;
mpWindowImpl->maPos.setY( nY );
bNewPos = true;
}
}
// the borderwindow always specifies the position for its client window if ( mpWindowImpl->mpBorderWindow )
mpWindowImpl->maPos = mpWindowImpl->mpBorderWindow->mpWindowImpl->maPos;
if ( mpWindowImpl->mpClientWindow )
{
mpWindowImpl->mpClientWindow->ImplPosSizeWindow( mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder,
mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder,
GetOutDev()->mnOutWidth - mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnRightBorder,
GetOutDev()->mnOutHeight - mpWindowImpl->mpClientWindow->mpWindowImpl->mnTopBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnBottomBorder,
PosSizeFlags::X | PosSizeFlags::Y |
PosSizeFlags::Width | PosSizeFlags::Height ); // If we have a client window, then this is the position // of the Application's floating windows
mpWindowImpl->mpClientWindow->mpWindowImpl->maPos = mpWindowImpl->maPos; if ( bNewPos )
{ if ( mpWindowImpl->mpClientWindow->IsVisible() )
{
mpWindowImpl->mpClientWindow->ImplCallMove();
} else
{
mpWindowImpl->mpClientWindow->mpWindowImpl->mbCallMove = true;
}
}
}
// Move()/Resize() will be called only for Show(), such that // at least one is called before Show() if ( IsVisible() )
{ if ( bNewPos )
{
ImplCallMove();
} if ( bNewSize )
{
ImplCallResize();
}
} else
{ if ( bNewPos )
mpWindowImpl->mbCallMove = true; if ( bNewSize )
mpWindowImpl->mbCallResize = true;
}
bool bUpdateSysObjClip = false; if ( IsReallyVisible() )
{ if ( bNewPos || bNewSize )
{ // set Clip-Flag
bUpdateSysObjClip = !ImplSetClipFlag( true );
}
SalInputContext aNewContext; const vcl::Font& rFont = rInputContext.GetFont(); const OUString& rFontName = rFont.GetFamilyName(); if (!rFontName.isEmpty())
{
OutputDevice *pFocusWinOutDev = pFocusWin->GetOutDev();
Size aSize = pFocusWinOutDev->ImplLogicToDevicePixel( rFont.GetFontSize() ); if ( !aSize.Height() )
{ // only set default sizes if the font height in logical // coordinates equals 0 if ( rFont.GetFontSize().Height() )
aSize.setHeight( 1 ); else
aSize.setHeight( (12*pFocusWin->GetOutDev()->mnDPIY)/72 );
}
aNewContext.mpFont =
pFocusWin->GetOutDev()->mxFontCache->GetFontInstance(
pFocusWin->GetOutDev()->mxFontCollection.get(),
rFont, aSize, static_cast<float>(aSize.Height()) );
}
aNewContext.mnOptions = rInputContext.GetOptions();
pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
}
void Window::SetDumpAsPropertyTreeHdl(const Link<tools::JsonWriter&, void>& rLink)
{ if (mpWindowImpl) // may be called after dispose
{
mpWindowImpl->maDumpAsPropertyTreeHdl = rLink;
}
}
void Window::KeyInput( const KeyEvent& rKEvt )
{ #ifndef _WIN32 // On Windows, dialogs react to accelerators without Alt (tdf#157649)
KeyCode cod = rKEvt.GetKeyCode ();
// do not respond to accelerators unless Alt or Ctrl is held if (cod.GetCode () >= 0x200 && cod.GetCode () <= 0x219)
{ bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel; if (autoacc && cod.GetModifier () != KEY_MOD2 && !(cod.GetModifier() & KEY_MOD1)) return;
} #endif
void Window::SetHelpHdl(const Link<vcl::Window&, bool>& rLink)
{ if (mpWindowImpl) // may be called after dispose
{
mpWindowImpl->maHelpRequestHdl = rLink;
}
}
void Window::RequestHelp( const HelpEvent& rHEvt )
{ // if Balloon-Help is requested, show the balloon // with help text set if ( rHEvt.GetMode() & HelpEventMode::BALLOON )
{
OUString rStr = GetHelpText(); if ( rStr.isEmpty() )
rStr = GetQuickHelpText(); if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
ImplGetParent()->RequestHelp( rHEvt ); else
{
Point aPos = GetPosPixel(); if ( ImplGetParent() && !ImplIsOverlapWindow() )
aPos = OutputToScreenPixel(Point(0, 0));
tools::Rectangle aRect( aPos, GetSizePixel() );
void Window::StateChanged(StateChangedType eType)
{ switch (eType)
{ //stuff that doesn't invalidate the layout case StateChangedType::ControlForeground: case StateChangedType::ControlBackground: case StateChangedType::UpdateMode: case StateChangedType::ReadOnly: case StateChangedType::Enable: case StateChangedType::State: case StateChangedType::Data: case StateChangedType::InitShow: case StateChangedType::ControlFocus: break; //stuff that does invalidate the layout default:
queue_resize(eType); break;
}
}
if( nBorderStyle == WindowBorderStyle::REMOVEBORDER &&
! mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame &&
mpWindowImpl->mpBorderWindow->mpWindowImpl->mpParent
)
{ // this is a little awkward: some controls (e.g. svtools ProgressBar) // cannot avoid getting constructed with WB_BORDER but want to disable // borders in case of NWF drawing. So they need a method to remove their border window
VclPtr<vcl::Window> pBorderWin = mpWindowImpl->mpBorderWindow; // remove us as border window's client
pBorderWin->mpWindowImpl->mpClientWindow = nullptr;
mpWindowImpl->mpBorderWindow = nullptr;
mpWindowImpl->mpRealParent = pBorderWin->mpWindowImpl->mpParent; // reparent us above the border window
SetParent( pBorderWin->mpWindowImpl->mpParent ); // set us to the position and size of our previous border
Point aBorderPos( pBorderWin->GetPosPixel() );
Size aBorderSize( pBorderWin->GetSizePixel() );
setPosSizePixel( aBorderPos.X(), aBorderPos.Y(), aBorderSize.Width(), aBorderSize.Height() ); // release border window
pBorderWin.disposeAndClear();
// set new style bits
SetStyle( GetStyle() & (~WB_BORDER) );
} else
{ if ( mpWindowImpl->mpBorderWindow->GetType() == WindowType::BORDERWINDOW ) static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetBorderStyle( nBorderStyle ); else
mpWindowImpl->mpBorderWindow->SetBorderStyle( nBorderStyle );
}
}
if ( !mpWindowImpl->mbFrame )
{ if (mpWindowImpl->mpWinData && mpWindowImpl->mpWinData->mbEnableNativeWidget)
{ /* * #i48371# native theming: some themes draw outside the control * area we tell them to (bad thing, but we cannot do much about it ). * On hiding these controls they get invalidated with their window rectangle * which leads to the parts outside the control area being left and not * invalidated. Workaround: invalidate an area on the parent, too
*/ constint workaround_border = 5;
tools::Rectangle aBounds( aInvRegion.GetBoundRect() );
aBounds.AdjustLeft( -workaround_border );
aBounds.AdjustTop( -workaround_border );
aBounds.AdjustRight(workaround_border );
aBounds.AdjustBottom(workaround_border );
aInvRegion = aBounds;
} if ( !mpWindowImpl->mbNoParentUpdate )
{ if ( !aInvRegion.IsEmpty() )
ImplInvalidateParentFrameRegion( aInvRegion );
}
ImplGenerateMouseMove();
}
}
} else
{ // inherit native widget flag for form controls // required here, because frames never show up in the child hierarchy - which should be fixed... // eg, the drop down of a combobox which is a system floating window if( mpWindowImpl->mbFrame && GetParent() && !GetParent()->isDisposed() &&
GetParent()->IsCompoundControl() &&
GetParent()->IsNativeWidgetEnabled() != IsNativeWidgetEnabled() &&
!(GetStyle() & WB_TOOLTIPWIN) )
{
EnableNativeWidget( GetParent()->IsNativeWidgetEnabled() );
}
if ( mpWindowImpl->mbCallMove )
{
ImplCallMove();
} if ( mpWindowImpl->mbCallResize )
{
ImplCallResize();
}
CompatStateChanged( StateChangedType::Visible );
vcl::Window* pTestParent; if ( ImplIsOverlapWindow() )
pTestParent = mpWindowImpl->mpOverlapWindow; else
pTestParent = ImplGetParent(); if ( mpWindowImpl->mbFrame || pTestParent->mpWindowImpl->mbReallyVisible )
{ // if a window becomes visible, send all child windows a StateChange, // such that these can initialise themselves
ImplCallInitShow();
// If it is a SystemWindow it automatically pops up on top of // all other windows if needed. if (ImplIsOverlapWindow())
{ if (!(nFlags & ShowFlags::NoActivate))
{
ImplStartToTop((nFlags & ShowFlags::ForegroundTask) ? ToTopFlags::ForegroundTask
: ToTopFlags::NONE);
ImplFocusToTop(ToTopFlags::NONE, false);
if (!(nFlags & ShowFlags::ForegroundTask))
{ // Inform user about window if we did not popup it at foreground
FlashWindow();
}
}
}
if ( mpWindowImpl->mpBorderWindow )
mpWindowImpl->mpBorderWindow->Show( true, nFlags ); elseif ( mpWindowImpl->mbFrame )
{ // #106431#, hide SplashScreen
ImplSVData* pSVData = ImplGetSVData(); if ( !pSVData->mpIntroWindow )
{ // The right way would be just to call this (not even in the 'if') auto pApp = GetpApp(); if ( pApp )
pApp->InitFinished();
} elseif ( !ImplIsWindowOrChild( pSVData->mpIntroWindow ) )
{ // ... but the VCL splash is broken, and it needs this // (for ./soffice .uno:NewDoc)
pSVData->mpIntroWindow->Hide();
}
// Query the correct size of the window, if we are waiting for // a system resize if ( mpWindowImpl->mbWaitSystemResize )
{
tools::Long nOutWidth;
tools::Long nOutHeight;
mpWindowImpl->mpFrame->GetClientSize( nOutWidth, nOutHeight );
ImplHandleResize( this, nOutWidth, nOutHeight );
}
if (mpWindowImpl->mpFrameData->mpBuffer && mpWindowImpl->mpFrameData->mpBuffer->GetOutputSizePixel() != GetOutputSizePixel()) // Make sure that the buffer size matches the window size, even if no resize was needed.
mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(GetOutputSizePixel());
}
if( !xWindow->mpWindowImpl ) return;
ImplShowAllOverlaps();
}
if( !xWindow->mpWindowImpl ) return;
// the SHOW/HIDE events also serve as indicators to send child creation/destroy events to the access bridge // However, the access bridge only uses this event if the data member is not NULL (it's kind of a hack that // we re-use the SHOW/HIDE events this way, with this particular semantics). // Since #104887#, the notifications for the access bridge are done in Impl(Set|Reset)ReallyVisible. Here, we // now only notify with a NULL data pointer, for all other clients except the access bridge. if ( !bRealVisibilityChanged )
CallEventListeners( mpWindowImpl->mbVisible ? VclEventId::WindowShow : VclEventId::WindowHide );
}
Size Window::GetSizePixel() const
{ if (!mpWindowImpl)
{
SAL_WARN("vcl.layout", "WTF no windowimpl"); return Size(0,0);
}
if ( !bEnable )
{ // the tracking mode will be stopped or the capture will be stolen // when a window is disabled, if ( IsTracking() )
EndTracking( TrackingEventFlags::Cancel ); if ( IsMouseCaptured() )
ReleaseMouse(); // try to pass focus to the next control // if the window has focus and is contained in the dialog control // mpWindowImpl->mbDisabled should only be set after a call of ImplDlgCtrlNextWindow(). // Otherwise ImplDlgCtrlNextWindow() should be used if ( HasFocus() )
ImplDlgCtrlNextWindow();
}
if ( (!bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled) || bEnable )
{ // automatically stop the tracking mode or steal capture // if the window is disabled if ( !bEnable )
{ if ( IsTracking() )
EndTracking( TrackingEventFlags::Cancel ); if ( IsMouseCaptured() )
ReleaseMouse();
}
// pExecuteWindow is the first Overlap-Frame --> if this // shouldn't be the case, then this must be changed in dialog.cxx if( pExcludeWindow )
pExcludeWindow = pExcludeWindow->ImplGetFirstOverlapWindow();
vcl::Window* pSysWin = mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mpFirstOverlap; while ( pSysWin )
{ // Is Window in the path from this window if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pSysWin, true ) )
{ // Is Window not in the exclude window path or not the // exclude window, then change the status if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pSysWin, true ) )
pSysWin->EnableInput( bEnable );
}
pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
}
// enable/disable floating system windows as well
vcl::Window* pFrameWin = ImplGetSVData()->maFrameData.mpFirstFrame; while ( pFrameWin )
{ if( pFrameWin->ImplIsFloatingWindow() )
{ // Is Window in the path from this window if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pFrameWin, true ) )
{ // Is Window not in the exclude window path or not the // exclude window, then change the status if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pFrameWin, true ) )
pFrameWin->EnableInput( bEnable );
}
}
pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
}
// the same for ownerdraw floating windows if( !mpWindowImpl->mbFrame ) return;
::std::vector< VclPtr<vcl::Window> >& rList = mpWindowImpl->mpFrameData->maOwnerDrawList; for (autoconst& elem : rList)
{ // Is Window in the path from this window if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( elem, true ) )
{ // Is Window not in the exclude window path or not the // exclude window, then change the status if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( elem, true ) )
elem->EnableInput( bEnable );
}
}
}
if ( nFlags & PosSizeFlags::Pos )
mpWindowImpl->mbDefPos = false; if ( nFlags & PosSizeFlags::Size )
mpWindowImpl->mbDefSize = false;
// The top BorderWindow is the window which is to be positioned
VclPtr<vcl::Window> pWindow = this; while ( pWindow->mpWindowImpl->mpBorderWindow )
pWindow = pWindow->mpWindowImpl->mpBorderWindow;
if ( pWindow->mpWindowImpl->mbFrame )
{ // Note: if we're positioning a frame, the coordinates are interpreted // as being the top-left corner of the window's client area and NOT // as the position of the border ! (due to limitations of several UNIX window managers)
tools::Long nOldWidth = pWindow->GetOutDev()->mnOutWidth;
if ( !(nFlags & PosSizeFlags::Width) )
nWidth = pWindow->GetOutDev()->mnOutWidth; if ( !(nFlags & PosSizeFlags::Height) )
nHeight = pWindow->GetOutDev()->mnOutHeight;
// Adjust resize with the hack of different client size and frame geometries to fix // native menu bars. Eventually this should be replaced by proper mnTopBorder usage.
pWindow->mpWindowImpl->mpFrame->GetClientSize(nWidth, nHeight);
// Resize should be called directly. If we haven't // set the correct size, we get a second resize from // the system with the correct size. This can be happened // if the size is too small or too large.
ImplHandleResize( pWindow, nWidth, nHeight );
} else
{
pWindow->ImplPosSizeWindow( nX, nY, nWidth, nHeight, nFlags ); if ( IsReallyVisible() )
ImplGenerateMouseMove();
}
}
Point Window::GetPosPixel() const
{ return mpWindowImpl->maPos;
}
if ( !ImplIsOverlapWindow() )
offx += mpWindowImpl->mpParent->GetOutDev()->mnOutOffX;
}
} return offx;
}
// normalized screen pixel are independent of mirroring
Point Window::OutputToNormalizedScreenPixel( const Point& rPos ) const
{ // relative to top level parent
tools::Long offx = ImplGetUnmirroredOutOffX(); return Point( rPos.X()+offx, rPos.Y() + GetOutDev()->mnOutOffY );
}
Point Window::NormalizedScreenToOutputPixel( const Point& rPos ) const
{ // relative to top level parent
tools::Long offx = ImplGetUnmirroredOutOffX(); return Point( rPos.X()-offx, rPos.Y() - GetOutDev()->mnOutOffY );
}
AbsoluteScreenPixelPoint Window::OutputToAbsoluteScreenPixel( const Point& rPos ) const
{ // relative to the screen
Point p = OutputToScreenPixel( rPos );
SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
p.AdjustX(g.x() );
p.AdjustY(g.y() ); return AbsoluteScreenPixelPoint(p);
}
Point Window::AbsoluteScreenToOutputPixel( const AbsoluteScreenPixelPoint& rPos ) const
{ // relative to the screen
Point p = ScreenToOutputPixel( Point(rPos) );
SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
p.AdjustX( -(g.x()) );
p.AdjustY( -(g.y()) ); return p;
}
AbsoluteScreenPixelRectangle Window::ImplOutputToUnmirroredAbsoluteScreenPixel( const tools::Rectangle &rRect ) const
{ // this method creates unmirrored screen coordinates to be compared with the desktop // and is used for positioning of RTL popup windows correctly on the screen
SalFrameGeometry g = mpWindowImpl->mpFrame->GetUnmirroredGeometry();
// with decoration
AbsoluteScreenPixelRectangle Window::GetWindowExtentsAbsolute() const
{ // make sure we use the extent of our border window, // otherwise we miss a few pixels const vcl::Window *pWin = mpWindowImpl->mpBorderWindow ? mpWindowImpl->mpBorderWindow : this;
AbsoluteScreenPixelPoint aPos( pWin->OutputToAbsoluteScreenPixel( Point(0,0) ) );
Size aSize ( pWin->GetSizePixel() ); // #104088# do not add decoration to the workwindow to be compatible to java accessibility api if( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && GetType() != WindowType::WORKWINDOW) )
{
SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
aPos.AdjustX( -sal_Int32(g.leftDecoration()) );
aPos.AdjustY( -sal_Int32(g.topDecoration()) );
aSize.AdjustWidth(g.leftDecoration() + g.rightDecoration() );
aSize.AdjustHeight(g.topDecoration() + g.bottomDecoration() );
} return AbsoluteScreenPixelRectangle( aPos, aSize );
}
// #107247# needed for accessibility // The VclEventId::WindowFrameTitleChanged is (mis)used to notify accessible name changes. // Therefore a window, which is labeled by this window, must also notify an accessible // name change. if ( IsReallyVisible() )
{
vcl::Window* pWindow = GetAccessibleRelationLabelFor(); if ( pWindow && pWindow != this )
pWindow->CallEventListeners( VclEventId::WindowFrameTitleChanged, &oldTitle );
}
CompatStateChanged( StateChangedType::Text );
}
OUString Window::GetText() const
{
return mpWindowImpl->maText;
}
OUString Window::GetDisplayText() const
{
return GetText();
}
const Wallpaper& Window::GetDisplayBackground() const
{ // FIXME: fix issue 52349, need to fix this really in // all NWF enabled controls const ToolBox* pTB = dynamic_cast<const ToolBox*>(this); if( pTB && IsNativeWidgetEnabled() ) return pTB->ImplGetToolBoxPrivateData()->maDisplayBackground;
//Fallback to Window::GetAccessibleDescription without reentry to GetHelpText() if (mpWindowImpl->maHelpText.isEmpty() && mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleDescription) return *mpWindowImpl->mpAccessibleInfos->pAccessibleDescription; return mpWindowImpl->maHelpText;
}
// be safe against re-entrance: first clear the old ref, then assign the new one if (mpWindowImpl->mxWindowPeer)
{ // first, disconnect the peer from ourself, otherwise disposing it, will dispose us
UnoWrapperBase* pWrapper = UnoWrapperBase::GetUnoWrapper();
SAL_WARN_IF( !pWrapper, "vcl.window", "SetComponentInterface: No Wrapper!" ); if ( pWrapper )
pWrapper->SetWindowInterface( nullptr, mpWindowImpl->mxWindowPeer );
mpWindowImpl->mxWindowPeer->dispose();
mpWindowImpl->mxWindowPeer.clear();
}
mpWindowImpl->mxWindowPeer = xPeer;
LOKWindowsMap& GetLOKWindowsMap()
{ // Map to remember the LOKWindowId <-> Window binding. static LOKWindowsMap s_aLOKWindowsMap;
return s_aLOKWindowsMap;
}
}
void Window::SetLOKNotifier(const vcl::ILibreOfficeKitNotifier* pNotifier, bool bParent)
{ // don't allow setting this twice
assert(mpWindowImpl->mpLOKNotifier == nullptr);
assert(pNotifier); // never use this in the desktop case
assert(comphelper::LibreOfficeKit::isActive());
if (!bParent)
{ // Counter to be able to have unique id's for each window. static vcl::LOKWindowId sLastLOKWindowId = 1;
// assign the LOK window id
assert(mpWindowImpl->mnLOKWindowId == 0);
mpWindowImpl->mnLOKWindowId = sLastLOKWindowId++;
GetLOKWindowsMap().emplace(mpWindowImpl->mnLOKWindowId, this);
}
mpWindowImpl->mpLOKNotifier = pNotifier;
}
VclPtr<Window> Window::FindLOKWindow(vcl::LOKWindowId nWindowId)
{ constauto it = GetLOKWindowsMap().find(nWindowId); if (it != GetLOKWindowsMap().end()) return it->second;
void Window::ReleaseLOKNotifier()
{ // unregister the LOK window binding if (mpWindowImpl->mnLOKWindowId > 0)
GetLOKWindowsMap().erase(mpWindowImpl->mnLOKWindowId);
while (pWindow && !pWindow->GetLOKNotifier())
pWindow = pWindow->GetParent();
return pWindow;
}
namespace
{
std::string_view windowTypeName(WindowType nWindowType)
{ switch (nWindowType)
{ case WindowType::NONE: return"none"; case WindowType::MESSBOX: return"messagebox"; case WindowType::INFOBOX: return"infobox"; case WindowType::WARNINGBOX: return"warningbox"; case WindowType::ERRORBOX: return"errorbox"; case WindowType::QUERYBOX: return"querybox"; case WindowType::WINDOW: return"window"; case WindowType::WORKWINDOW: return"workwindow"; case WindowType::CONTAINER: return"container"; case WindowType::FLOATINGWINDOW: return"floatingwindow"; case WindowType::DIALOG: return"dialog"; case WindowType::MODELESSDIALOG: return"modelessdialog"; case WindowType::CONTROL: return"control"; case WindowType::PUSHBUTTON: return"pushbutton"; case WindowType::OKBUTTON: return"okbutton"; case WindowType::CANCELBUTTON: return"cancelbutton"; case WindowType::HELPBUTTON: return"helpbutton"; case WindowType::IMAGEBUTTON: return"imagebutton"; case WindowType::MENUBUTTON: return"menubutton"; case WindowType::MOREBUTTON: return"morebutton"; case WindowType::SPINBUTTON: return"spinbutton"; case WindowType::RADIOBUTTON: return"radiobutton"; case WindowType::CHECKBOX: return"checkbox"; case WindowType::TRISTATEBOX: return"tristatebox"; case WindowType::EDIT: return"edit"; case WindowType::MULTILINEEDIT: return"multilineedit"; case WindowType::COMBOBOX: return"combobox"; case WindowType::LISTBOX: return"listbox"; case WindowType::MULTILISTBOX: return"multilistbox"; case WindowType::FIXEDTEXT: return"fixedtext"; case WindowType::FIXEDLINE: return"fixedline"; case WindowType::FIXEDBITMAP: return"fixedbitmap"; case WindowType::FIXEDIMAGE: return"fixedimage"; case WindowType::GROUPBOX: return"groupbox"; case WindowType::SCROLLBAR: return"scrollbar"; case WindowType::SCROLLBARBOX: return"scrollbarbox"; case WindowType::SPLITTER: return"splitter"; case WindowType::SPLITWINDOW: return"splitwindow"; case WindowType::SPINFIELD: return"spinfield"; case WindowType::PATTERNFIELD: return"patternfield"; case WindowType::METRICFIELD: return"metricfield"; case WindowType::FORMATTEDFIELD: return"formattedfield"; case WindowType::CURRENCYFIELD: return"currencyfield"; case WindowType::DATEFIELD: return"datefield"; case WindowType::TIMEFIELD: return"timefield"; case WindowType::PATTERNBOX: return"patternbox"; case WindowType::NUMERICBOX: return"numericbox"; case WindowType::METRICBOX: return"metricbox"; case WindowType::CURRENCYBOX: return"currencybox"; case WindowType::DATEBOX: return"datebox"; case WindowType::TIMEBOX: return"timebox"; case WindowType::LONGCURRENCYBOX: return"longcurrencybox"; case WindowType::SCROLLWINDOW: return"scrollwindow"; case WindowType::TOOLBOX: return"toolbox"; case WindowType::DOCKINGWINDOW: return"dockingwindow"; case WindowType::STATUSBAR: return"statusbar"; case WindowType::TABPAGE: return"tabpage"; case WindowType::TABCONTROL: return"tabcontrol"; case WindowType::TABDIALOG: return"tabdialog"; case WindowType::BORDERWINDOW: return"borderwindow"; case WindowType::BUTTONDIALOG: return"buttondialog"; case WindowType::SYSTEMCHILDWINDOW: return"systemchildwindow"; case WindowType::SLIDER: return"slider"; case WindowType::MENUBARWINDOW: return"menubarwindow"; case WindowType::TREELISTBOX: return"treelistbox"; case WindowType::HELPTEXTWINDOW: return"helptextwindow"; case WindowType::INTROWINDOW: return"introwindow"; case WindowType::LISTBOXWINDOW: return"listboxwindow"; case WindowType::DOCKINGAREA: return"dockingarea"; case WindowType::RULER: return"ruler"; case WindowType::HEADERBAR: return"headerbar"; case WindowType::VERTICALTABCONTROL: return"verticaltabcontrol"; case WindowType::PROGRESSBAR: return"progressbar"; case WindowType::LINK_BUTTON: return"linkbutton";
// nothing to do here, but for completeness case WindowType::TOOLKIT_FRAMEWINDOW: return"toolkit_framewindow"; case WindowType::TOOLKIT_SYSTEMCHILDWINDOW: return"toolkit_systemchildwindow";
}
return"none";
}
}
void Window::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{ if (!mpWindowImpl) return;
rJsonWriter.put("id", get_id()); // TODO could be missing - sort out
rJsonWriter.put("type", windowTypeName(GetType()));
rJsonWriter.put("text", GetText());
rJsonWriter.put("enabled", IsEnabled()); if (!IsVisible())
rJsonWriter.put("visible", false);
if (vcl::Window* pChild = mpWindowImpl->mpFirstChild)
{ auto childrenNode = rJsonWriter.startArray("children"); while (pChild)
{
{ auto childNode = rJsonWriter.startStruct();
pChild->DumpAsPropertyTree(rJsonWriter);
sal_Int32 nLeft = pChild->get_grid_left_attach();
sal_Int32 nTop = pChild->get_grid_top_attach(); if (nLeft != -1 && nTop != -1)
{
rJsonWriter.put("left", nLeft);
rJsonWriter.put("top", nTop);
}
if (!sAccName.isEmpty() || !sAccDesc.isEmpty())
{ auto aAria = rJsonWriter.startNode("aria"); if (!sAccName.isEmpty())
rJsonWriter.put("label", sAccName); if (!sAccDesc.isEmpty())
rJsonWriter.put("description", sAccDesc);
}
}
void Window::ImplCallDeactivateListeners( vcl::Window *pNew )
{ // no deactivation if the newly activated window is my child if ( !pNew || !ImplIsChild( pNew ) )
{
VclPtr<vcl::Window> xWindow(this);
CallEventListeners( VclEventId::WindowDeactivate, pNew ); if( !xWindow->mpWindowImpl ) return;
// #100759#, avoid walking the wrong frame's hierarchy // eg, undocked docking windows (ImplDockFloatWin) if ( ImplGetParent() && ImplGetParent()->mpWindowImpl &&
mpWindowImpl->mpFrameWindow == ImplGetParent()->mpWindowImpl->mpFrameWindow )
ImplGetParent()->ImplCallDeactivateListeners( pNew );
}
}
void Window::ImplCallActivateListeners( vcl::Window *pOld )
{ // no activation if the old active window is my child if ( pOld && ImplIsChild( pOld )) return;
// frame based modal counter (dialogs are not modal to the whole application anymore) bool Window::IsInModalMode() const
{ return (mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mnModalMode != 0);
}
// send datachanged event to allow for internal changes required for NWF // like clipmode, transparency, etc.
DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, &*GetOutDev()->moSettings, AllSettingsFlags::STYLE );
CompatDataChanged( aDCEvt );
// sometimes the borderwindow is queried, so keep it in sync if( mpWindowImpl->mpBorderWindow )
mpWindowImpl->mpBorderWindow->ImplGetWinData()->mbEnableNativeWidget = bEnable;
}
// this is a rubbish implementation using a11y, ideally all subclasses implementing // GetSurroundingText/GetSurroundingTextSelection should implement this and then this // should be removed in favor of a stub that returns false bool Window::DeleteSurroundingText(const Selection& rSelection)
{
uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText(this); if (xText.is())
{
sal_Int32 nPosition = xText->getCaretPosition(); // #i111768# range checking
sal_Int32 nDeletePos = rSelection.Min();
sal_Int32 nDeleteEnd = rSelection.Max(); if (nDeletePos < 0)
nDeletePos = 0; if (nDeleteEnd < 0)
nDeleteEnd = 0; if (nDeleteEnd > xText->getCharacterCount())
nDeleteEnd = xText->getCharacterCount();
xText->deleteText(nDeletePos, nDeleteEnd); //tdf91641 adjust cursor if deleted chars shift it forward (normal case) if (nDeletePos < nPosition)
{ if (nDeleteEnd <= nPosition)
nPosition = nPosition - (nDeleteEnd - nDeletePos); else
nPosition = nDeletePos;
if (xText->getCharacterCount() >= nPosition)
xText->setCaretPosition( nPosition );
} returntrue;
}
void Window::RequestDoubleBuffering(bool bRequest)
{ if (bRequest)
{
mpWindowImpl->mpFrameData->mpBuffer = VclPtrInstance<VirtualDevice>(); // Make sure that the buffer size matches the frame size.
mpWindowImpl->mpFrameData->mpBuffer->SetOutputSizePixel(mpWindowImpl->mpFrameWindow->GetOutputSizePixel());
} else
mpWindowImpl->mpFrameData->mpBuffer.reset();
}
/* * The rationale here is that we moved destructors to * dispose and this altered a lot of code paths, that * are better left unchanged for now.
*/ void Window::CompatGetFocus()
{ if (!mpWindowImpl || mpWindowImpl->mbInDispose)
Window::GetFocus(); else
GetFocus();
}
void WindowOutputDevice::dispose()
{
assert((!mxOwnerWindow || mxOwnerWindow->isDisposed()) && "This belongs to the associated window and must be disposed after it");
::OutputDevice::dispose(); // need to do this after OutputDevice::dispose so that the call to WindowOutputDevice::ReleaseGraphics // can release the graphics properly
mxOwnerWindow.reset();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.