1157 lines
39 KiB
C++
1157 lines
39 KiB
C++
/* -*- 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 .
|
|
*/
|
|
|
|
#include <vcl/syswin.hxx>
|
|
#include <vcl/window.hxx>
|
|
#include <vcl/taskpanelist.hxx>
|
|
#include <sal/log.hxx>
|
|
|
|
#include <salframe.hxx>
|
|
#include <salobj.hxx>
|
|
#include <svdata.hxx>
|
|
#include <window.h>
|
|
#include <brdwin.hxx>
|
|
|
|
#include <com/sun/star/awt/XTopWindow.hpp>
|
|
#include <com/sun/star/awt/XVclWindowPeer.hpp>
|
|
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::datatransfer::clipboard;
|
|
using namespace ::com::sun::star::datatransfer::dnd;
|
|
using namespace ::com::sun::star;
|
|
|
|
using ::com::sun::star::awt::XTopWindow;
|
|
|
|
struct ImplCalcToTopData
|
|
{
|
|
std::unique_ptr<ImplCalcToTopData> mpNext;
|
|
VclPtr<vcl::Window> mpWindow;
|
|
std::unique_ptr<vcl::Region> mpInvalidateRegion;
|
|
};
|
|
|
|
namespace vcl {
|
|
|
|
vcl::Window* Window::ImplGetTopmostFrameWindow() const
|
|
{
|
|
const vcl::Window *pTopmostParent = this;
|
|
while( pTopmostParent->ImplGetParent() )
|
|
pTopmostParent = pTopmostParent->ImplGetParent();
|
|
return pTopmostParent->mpWindowImpl->mpFrameWindow;
|
|
}
|
|
|
|
void Window::ImplInsertWindow( vcl::Window* pParent )
|
|
{
|
|
mpWindowImpl->mpParent = pParent;
|
|
mpWindowImpl->mpRealParent = pParent;
|
|
|
|
if ( !pParent || mpWindowImpl->mbFrame )
|
|
return;
|
|
|
|
// search frame window and set window frame data
|
|
vcl::Window* pFrameParent = pParent->mpWindowImpl->mpFrameWindow;
|
|
mpWindowImpl->mpFrameData = pFrameParent->mpWindowImpl->mpFrameData;
|
|
if (mpWindowImpl->mpFrame != pFrameParent->mpWindowImpl->mpFrame)
|
|
{
|
|
mpWindowImpl->mpFrame = pFrameParent->mpWindowImpl->mpFrame;
|
|
if (mpWindowImpl->mpSysObj)
|
|
mpWindowImpl->mpSysObj->Reparent(mpWindowImpl->mpFrame);
|
|
}
|
|
mpWindowImpl->mpFrameWindow = pFrameParent;
|
|
mpWindowImpl->mbFrame = false;
|
|
|
|
// search overlap window and insert window in list
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
vcl::Window* pFirstOverlapParent = pParent;
|
|
while ( !pFirstOverlapParent->ImplIsOverlapWindow() )
|
|
pFirstOverlapParent = pFirstOverlapParent->ImplGetParent();
|
|
mpWindowImpl->mpOverlapWindow = pFirstOverlapParent;
|
|
|
|
mpWindowImpl->mpNextOverlap = mpWindowImpl->mpFrameData->mpFirstOverlap;
|
|
mpWindowImpl->mpFrameData->mpFirstOverlap = this;
|
|
|
|
// Overlap-Windows are by default the uppermost
|
|
mpWindowImpl->mpNext = pFirstOverlapParent->mpWindowImpl->mpFirstOverlap;
|
|
pFirstOverlapParent->mpWindowImpl->mpFirstOverlap = this;
|
|
if ( !pFirstOverlapParent->mpWindowImpl->mpLastOverlap )
|
|
pFirstOverlapParent->mpWindowImpl->mpLastOverlap = this;
|
|
else
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = this;
|
|
}
|
|
else
|
|
{
|
|
if ( pParent->ImplIsOverlapWindow() )
|
|
mpWindowImpl->mpOverlapWindow = pParent;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow = pParent->mpWindowImpl->mpOverlapWindow;
|
|
mpWindowImpl->mpPrev = pParent->mpWindowImpl->mpLastChild;
|
|
pParent->mpWindowImpl->mpLastChild = this;
|
|
if ( !pParent->mpWindowImpl->mpFirstChild )
|
|
pParent->mpWindowImpl->mpFirstChild = this;
|
|
else
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
}
|
|
}
|
|
|
|
void Window::ImplRemoveWindow( bool bRemoveFrameData )
|
|
{
|
|
// remove window from the lists
|
|
if ( !mpWindowImpl->mbFrame )
|
|
{
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
if ( mpWindowImpl->mpFrameData->mpFirstOverlap.get() == this )
|
|
mpWindowImpl->mpFrameData->mpFirstOverlap = mpWindowImpl->mpNextOverlap;
|
|
else
|
|
{
|
|
vcl::Window* pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap;
|
|
while ( pTempWin->mpWindowImpl->mpNextOverlap.get() != this )
|
|
pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
|
|
pTempWin->mpWindowImpl->mpNextOverlap = mpWindowImpl->mpNextOverlap;
|
|
}
|
|
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
|
|
}
|
|
else
|
|
{
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else if ( mpWindowImpl->mpParent )
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else if ( mpWindowImpl->mpParent )
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = mpWindowImpl->mpPrev;
|
|
}
|
|
|
|
mpWindowImpl->mpPrev = nullptr;
|
|
mpWindowImpl->mpNext = nullptr;
|
|
}
|
|
|
|
if ( bRemoveFrameData )
|
|
{
|
|
// release the graphic
|
|
OutputDevice *pOutDev = GetOutDev();
|
|
pOutDev->ReleaseGraphics();
|
|
}
|
|
}
|
|
|
|
void Window::reorderWithinParent(sal_uInt16 nNewPosition)
|
|
{
|
|
sal_uInt16 nChildCount = 0;
|
|
vcl::Window *pSource = mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild;
|
|
while (pSource)
|
|
{
|
|
if (nChildCount == nNewPosition)
|
|
break;
|
|
pSource = pSource->mpWindowImpl->mpNext;
|
|
nChildCount++;
|
|
}
|
|
|
|
if (pSource == this) //already at the right place
|
|
return;
|
|
|
|
ImplRemoveWindow(false);
|
|
|
|
if (pSource)
|
|
{
|
|
mpWindowImpl->mpNext = pSource;
|
|
mpWindowImpl->mpPrev = pSource->mpWindowImpl->mpPrev;
|
|
pSource->mpWindowImpl->mpPrev = this;
|
|
}
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = this;
|
|
|
|
if (mpWindowImpl->mpPrev)
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = this;
|
|
}
|
|
|
|
void Window::ImplToBottomChild()
|
|
{
|
|
if ( ImplIsOverlapWindow() || mpWindowImpl->mbReallyVisible || (mpWindowImpl->mpParent->mpWindowImpl->mpLastChild.get() == this) )
|
|
return;
|
|
|
|
// put the window to the end of the list
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
{
|
|
// coverity[copy_paste_error : FALSE] - this is correct mpFirstChild, not mpNext
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
|
|
}
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
mpWindowImpl->mpPrev = mpWindowImpl->mpParent->mpWindowImpl->mpLastChild;
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = this;
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
mpWindowImpl->mpNext = nullptr;
|
|
}
|
|
|
|
void Window::ImplCalcToTop( ImplCalcToTopData* pPrevData )
|
|
{
|
|
SAL_WARN_IF( !ImplIsOverlapWindow(), "vcl", "Window::ImplCalcToTop(): Is not an OverlapWindow" );
|
|
|
|
if ( mpWindowImpl->mbFrame )
|
|
return;
|
|
|
|
if ( !IsReallyVisible() )
|
|
return;
|
|
|
|
// calculate region, where the window overlaps with other windows
|
|
vcl::Region aRegion( GetOutputRectPixel() );
|
|
vcl::Region aInvalidateRegion;
|
|
ImplCalcOverlapRegionOverlaps( aRegion, aInvalidateRegion );
|
|
|
|
if ( !aInvalidateRegion.IsEmpty() )
|
|
{
|
|
ImplCalcToTopData* pData = new ImplCalcToTopData;
|
|
pPrevData->mpNext.reset(pData);
|
|
pData->mpWindow = this;
|
|
pData->mpInvalidateRegion.reset(new vcl::Region(std::move(aInvalidateRegion)));
|
|
}
|
|
}
|
|
|
|
void Window::ImplToTop( ToTopFlags nFlags )
|
|
{
|
|
SAL_WARN_IF( !ImplIsOverlapWindow(), "vcl", "Window::ImplToTop(): Is not an OverlapWindow" );
|
|
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
// on a mouse click in the external window, it is the latter's
|
|
// responsibility to assure our frame is put in front
|
|
if ( !mpWindowImpl->mpFrameData->mbHasFocus &&
|
|
!mpWindowImpl->mpFrameData->mbSysObjFocus &&
|
|
!mpWindowImpl->mpFrameData->mbInSysObjFocusHdl &&
|
|
!mpWindowImpl->mpFrameData->mbInSysObjToTopHdl )
|
|
{
|
|
// do not bring floating windows on the client to top
|
|
if( !ImplGetClientWindow() || !(ImplGetClientWindow()->GetStyle() & WB_SYSTEMFLOATWIN) )
|
|
{
|
|
SalFrameToTop nSysFlags = SalFrameToTop::NONE;
|
|
if ( nFlags & ToTopFlags::RestoreWhenMin )
|
|
nSysFlags |= SalFrameToTop::RestoreWhenMin;
|
|
if ( nFlags & ToTopFlags::ForegroundTask )
|
|
nSysFlags |= SalFrameToTop::ForegroundTask;
|
|
if ( nFlags & ToTopFlags::GrabFocusOnly )
|
|
nSysFlags |= SalFrameToTop::GrabFocusOnly;
|
|
mpWindowImpl->mpFrame->ToTop( nSysFlags );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap.get() != this )
|
|
{
|
|
// remove window from the list
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
{
|
|
// coverity[copy_paste_error : FALSE] - this is correct mpLastOverlap, not mpPrev
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
|
|
}
|
|
|
|
// take AlwaysOnTop into account
|
|
bool bOnTop = IsAlwaysOnTopEnabled();
|
|
vcl::Window* pNextWin = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
|
|
if ( !bOnTop )
|
|
{
|
|
while ( pNextWin )
|
|
{
|
|
if ( !pNextWin->IsAlwaysOnTopEnabled() )
|
|
break;
|
|
pNextWin = pNextWin->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// add the window to the list again
|
|
mpWindowImpl->mpNext = pNextWin;
|
|
if ( pNextWin )
|
|
{
|
|
mpWindowImpl->mpPrev = pNextWin->mpWindowImpl->mpPrev;
|
|
pNextWin->mpWindowImpl->mpPrev = this;
|
|
}
|
|
else
|
|
{
|
|
mpWindowImpl->mpPrev = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap;
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = this;
|
|
}
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = this;
|
|
|
|
// recalculate ClipRegion of this and all overlapping windows
|
|
if ( IsReallyVisible() )
|
|
{
|
|
mpWindowImpl->mpOverlapWindow->ImplSetClipFlagOverlapWindows();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Window::ImplStartToTop( ToTopFlags nFlags )
|
|
{
|
|
ImplCalcToTopData aStartData;
|
|
ImplCalcToTopData* pCurData;
|
|
vcl::Window* pOverlapWindow;
|
|
if ( ImplIsOverlapWindow() )
|
|
pOverlapWindow = this;
|
|
else
|
|
pOverlapWindow = mpWindowImpl->mpOverlapWindow;
|
|
|
|
// first calculate paint areas
|
|
vcl::Window* pTempOverlapWindow = pOverlapWindow;
|
|
aStartData.mpNext = nullptr;
|
|
pCurData = &aStartData;
|
|
do
|
|
{
|
|
pTempOverlapWindow->ImplCalcToTop( pCurData );
|
|
if ( pCurData->mpNext )
|
|
pCurData = pCurData->mpNext.get();
|
|
pTempOverlapWindow = pTempOverlapWindow->mpWindowImpl->mpOverlapWindow;
|
|
}
|
|
while ( !pTempOverlapWindow->mpWindowImpl->mbFrame );
|
|
// next calculate the paint areas of the ChildOverlap windows
|
|
pTempOverlapWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pTempOverlapWindow )
|
|
{
|
|
pTempOverlapWindow->ImplCalcToTop( pCurData );
|
|
if ( pCurData->mpNext )
|
|
pCurData = pCurData->mpNext.get();
|
|
pTempOverlapWindow = pTempOverlapWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
// and next change the windows list
|
|
pTempOverlapWindow = pOverlapWindow;
|
|
do
|
|
{
|
|
pTempOverlapWindow->ImplToTop( nFlags );
|
|
pTempOverlapWindow = pTempOverlapWindow->mpWindowImpl->mpOverlapWindow;
|
|
}
|
|
while ( !pTempOverlapWindow->mpWindowImpl->mbFrame );
|
|
// as last step invalidate the invalid areas
|
|
pCurData = aStartData.mpNext.get();
|
|
while ( pCurData )
|
|
{
|
|
pCurData->mpWindow->ImplInvalidateFrameRegion( pCurData->mpInvalidateRegion.get(), InvalidateFlags::Children );
|
|
pCurData = pCurData->mpNext.get();
|
|
}
|
|
}
|
|
|
|
void Window::ImplFocusToTop( ToTopFlags nFlags, bool bReallyVisible )
|
|
{
|
|
// do we need to fetch the focus?
|
|
if ( !(nFlags & ToTopFlags::NoGrabFocus) )
|
|
{
|
|
// first window with GrabFocus-Activate gets the focus
|
|
vcl::Window* pFocusWindow = this;
|
|
while ( !pFocusWindow->ImplIsOverlapWindow() )
|
|
{
|
|
// if the window has no BorderWindow, we
|
|
// should always find the belonging BorderWindow
|
|
if ( !pFocusWindow->mpWindowImpl->mpBorderWindow )
|
|
{
|
|
if ( pFocusWindow->mpWindowImpl->mnActivateMode & ActivateModeFlags::GrabFocus )
|
|
break;
|
|
}
|
|
pFocusWindow = pFocusWindow->ImplGetParent();
|
|
}
|
|
if ( (pFocusWindow->mpWindowImpl->mnActivateMode & ActivateModeFlags::GrabFocus) &&
|
|
!pFocusWindow->HasChildPathFocus( true ) )
|
|
pFocusWindow->GrabFocus();
|
|
}
|
|
|
|
if ( bReallyVisible )
|
|
ImplGenerateMouseMove();
|
|
}
|
|
|
|
void Window::ImplShowAllOverlaps()
|
|
{
|
|
vcl::Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow )
|
|
{
|
|
if ( pOverlapWindow->mpWindowImpl->mbOverlapVisible )
|
|
{
|
|
pOverlapWindow->Show( true, ShowFlags::NoActivate );
|
|
pOverlapWindow->mpWindowImpl->mbOverlapVisible = false;
|
|
}
|
|
|
|
pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
void Window::ImplHideAllOverlaps()
|
|
{
|
|
vcl::Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow )
|
|
{
|
|
if ( pOverlapWindow->IsVisible() )
|
|
{
|
|
pOverlapWindow->mpWindowImpl->mbOverlapVisible = true;
|
|
pOverlapWindow->Show( false );
|
|
}
|
|
|
|
pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
void Window::ToTop( ToTopFlags nFlags )
|
|
{
|
|
if (!mpWindowImpl)
|
|
return;
|
|
|
|
ImplStartToTop( nFlags );
|
|
ImplFocusToTop( nFlags, IsReallyVisible() );
|
|
}
|
|
|
|
void Window::SetZOrder( vcl::Window* pRefWindow, ZOrderFlags nFlags )
|
|
{
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
mpWindowImpl->mpBorderWindow->SetZOrder( pRefWindow, nFlags );
|
|
return;
|
|
}
|
|
|
|
if ( nFlags & ZOrderFlags::First )
|
|
{
|
|
if ( ImplIsOverlapWindow() )
|
|
pRefWindow = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
|
|
else
|
|
pRefWindow = mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild;
|
|
nFlags |= ZOrderFlags::Before;
|
|
}
|
|
else if ( nFlags & ZOrderFlags::Last )
|
|
{
|
|
if ( ImplIsOverlapWindow() )
|
|
pRefWindow = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap;
|
|
else
|
|
pRefWindow = mpWindowImpl->mpParent->mpWindowImpl->mpLastChild;
|
|
nFlags |= ZOrderFlags::Behind;
|
|
}
|
|
|
|
while ( pRefWindow && pRefWindow->mpWindowImpl->mpBorderWindow )
|
|
pRefWindow = pRefWindow->mpWindowImpl->mpBorderWindow;
|
|
if (!pRefWindow || pRefWindow == this || mpWindowImpl->mbFrame)
|
|
return;
|
|
|
|
SAL_WARN_IF( pRefWindow->mpWindowImpl->mpParent != mpWindowImpl->mpParent, "vcl", "Window::SetZOrder() - pRefWindow has other parent" );
|
|
if ( nFlags & ZOrderFlags::Before )
|
|
{
|
|
if ( pRefWindow->mpWindowImpl->mpPrev.get() == this )
|
|
return;
|
|
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
|
|
if ( !pRefWindow->mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = this;
|
|
}
|
|
else
|
|
{
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = mpWindowImpl->mpPrev;
|
|
if ( !pRefWindow->mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = this;
|
|
}
|
|
|
|
mpWindowImpl->mpPrev = pRefWindow->mpWindowImpl->mpPrev;
|
|
mpWindowImpl->mpNext = pRefWindow;
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = this;
|
|
}
|
|
else if ( nFlags & ZOrderFlags::Behind )
|
|
{
|
|
if ( pRefWindow->mpWindowImpl->mpNext.get() == this )
|
|
return;
|
|
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
|
|
if ( !pRefWindow->mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = this;
|
|
}
|
|
else
|
|
{
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = mpWindowImpl->mpPrev;
|
|
if ( !pRefWindow->mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = this;
|
|
}
|
|
|
|
mpWindowImpl->mpPrev = pRefWindow;
|
|
mpWindowImpl->mpNext = pRefWindow->mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = this;
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
}
|
|
|
|
if ( !IsReallyVisible() )
|
|
return;
|
|
|
|
if ( !mpWindowImpl->mbInitWinClipRegion && mpWindowImpl->maWinClipRegion.IsEmpty() )
|
|
return;
|
|
|
|
bool bInitWinClipRegion = mpWindowImpl->mbInitWinClipRegion;
|
|
ImplSetClipFlag();
|
|
|
|
// When ClipRegion was not initialised, assume
|
|
// the window has not been sent, therefore do not
|
|
// trigger any Invalidates. This is an optimization
|
|
// for HTML documents with many controls. If this
|
|
// check gives problems, a flag should be introduced
|
|
// which tracks whether the window has already been
|
|
// emitted after Show
|
|
if ( bInitWinClipRegion )
|
|
return;
|
|
|
|
// Invalidate all windows which are next to each other
|
|
// Is INCOMPLETE !!!
|
|
tools::Rectangle aWinRect = GetOutputRectPixel();
|
|
vcl::Window* pWindow = nullptr;
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
if ( mpWindowImpl->mpOverlapWindow )
|
|
pWindow = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
|
|
}
|
|
else
|
|
pWindow = ImplGetParent()->mpWindowImpl->mpFirstChild;
|
|
// Invalidate all windows in front of us and which are covered by us
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow == this )
|
|
break;
|
|
tools::Rectangle aCompRect = pWindow->GetOutputRectPixel();
|
|
if ( aWinRect.Overlaps( aCompRect ) )
|
|
pWindow->Invalidate( InvalidateFlags::Children | InvalidateFlags::NoTransparent );
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
// If we are covered by a window in the background
|
|
// we should redraw it
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow != this )
|
|
{
|
|
tools::Rectangle aCompRect = pWindow->GetOutputRectPixel();
|
|
if ( aWinRect.Overlaps( aCompRect ) )
|
|
{
|
|
Invalidate( InvalidateFlags::Children | InvalidateFlags::NoTransparent );
|
|
break;
|
|
}
|
|
}
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
void Window::EnableAlwaysOnTop( bool bEnable )
|
|
{
|
|
|
|
mpWindowImpl->mbAlwaysOnTop = bEnable;
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->EnableAlwaysOnTop( bEnable );
|
|
else if ( bEnable && IsReallyVisible() )
|
|
ToTop();
|
|
|
|
if ( mpWindowImpl->mbFrame )
|
|
mpWindowImpl->mpFrame->SetAlwaysOnTop( bEnable );
|
|
}
|
|
|
|
bool Window::IsTopWindow() const
|
|
{
|
|
if ( !mpWindowImpl || mpWindowImpl->mbInDispose )
|
|
return false;
|
|
|
|
// topwindows must be frames or they must have a borderwindow which is a frame
|
|
if( !mpWindowImpl->mbFrame && (!mpWindowImpl->mpBorderWindow || !mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame ) )
|
|
return false;
|
|
|
|
ImplGetWinData();
|
|
if( mpWindowImpl->mpWinData->mnIsTopWindow == sal_uInt16(~0)) // still uninitialized
|
|
{
|
|
// #113722#, cache result of expensive queryInterface call
|
|
vcl::Window *pThisWin = const_cast<vcl::Window*>(this);
|
|
uno::Reference< XTopWindow > xTopWindow( pThisWin->GetComponentInterface(), UNO_QUERY );
|
|
pThisWin->mpWindowImpl->mpWinData->mnIsTopWindow = xTopWindow.is() ? 1 : 0;
|
|
}
|
|
return mpWindowImpl->mpWinData->mnIsTopWindow == 1;
|
|
}
|
|
|
|
vcl::Window* Window::ImplFindWindow( const Point& rFramePos )
|
|
{
|
|
vcl::Window* pTempWindow;
|
|
vcl::Window* pFindWindow;
|
|
|
|
// first check all overlapping windows
|
|
pTempWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pTempWindow )
|
|
{
|
|
pFindWindow = pTempWindow->ImplFindWindow( rFramePos );
|
|
if ( pFindWindow )
|
|
return pFindWindow;
|
|
pTempWindow = pTempWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
// then we check our window
|
|
if ( !mpWindowImpl->mbVisible )
|
|
return nullptr;
|
|
|
|
WindowHitTest nHitTest = ImplHitTest( rFramePos );
|
|
if ( nHitTest & WindowHitTest::Inside )
|
|
{
|
|
// and then we check all child windows
|
|
pTempWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pTempWindow )
|
|
{
|
|
pFindWindow = pTempWindow->ImplFindWindow( rFramePos );
|
|
if ( pFindWindow )
|
|
return pFindWindow;
|
|
pTempWindow = pTempWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
if ( nHitTest & WindowHitTest::Transparent )
|
|
return nullptr;
|
|
else
|
|
return this;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
bool Window::ImplIsRealParentPath( const vcl::Window* pWindow ) const
|
|
{
|
|
pWindow = pWindow->GetParent();
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow == this )
|
|
return true;
|
|
pWindow = pWindow->GetParent();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Window::ImplIsChild( const vcl::Window* pWindow, bool bSystemWindow ) const
|
|
{
|
|
do
|
|
{
|
|
if ( !bSystemWindow && pWindow->ImplIsOverlapWindow() )
|
|
break;
|
|
|
|
pWindow = pWindow->ImplGetParent();
|
|
|
|
if ( pWindow == this )
|
|
return true;
|
|
}
|
|
while ( pWindow );
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Window::ImplIsWindowOrChild( const vcl::Window* pWindow, bool bSystemWindow ) const
|
|
{
|
|
if ( this == pWindow )
|
|
return true;
|
|
return ImplIsChild( pWindow, bSystemWindow );
|
|
}
|
|
|
|
void Window::ImplResetReallyVisible()
|
|
{
|
|
bool bBecameReallyInvisible = mpWindowImpl->mbReallyVisible;
|
|
|
|
GetOutDev()->mbDevOutput = false;
|
|
mpWindowImpl->mbReallyVisible = false;
|
|
mpWindowImpl->mbReallyShown = false;
|
|
|
|
// 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.
|
|
if( bBecameReallyInvisible && ImplIsAccessibleCandidate() )
|
|
CallEventListeners( VclEventId::WindowHide, this );
|
|
// TODO. It's kind of a hack that we're re-using the VclEventId::WindowHide. Normally, we should
|
|
// introduce another event which explicitly triggers the Accessibility implementations.
|
|
|
|
vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible )
|
|
pWindow->ImplResetReallyVisible();
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible )
|
|
pWindow->ImplResetReallyVisible();
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
void Window::ImplUpdateWindowPtr( vcl::Window* pWindow )
|
|
{
|
|
if ( mpWindowImpl->mpFrameWindow != pWindow->mpWindowImpl->mpFrameWindow )
|
|
{
|
|
// release graphic
|
|
OutputDevice *pOutDev = GetOutDev();
|
|
pOutDev->ReleaseGraphics();
|
|
}
|
|
|
|
mpWindowImpl->mpFrameData = pWindow->mpWindowImpl->mpFrameData;
|
|
if (mpWindowImpl->mpFrame != pWindow->mpWindowImpl->mpFrame)
|
|
{
|
|
mpWindowImpl->mpFrame = pWindow->mpWindowImpl->mpFrame;
|
|
if (mpWindowImpl->mpSysObj)
|
|
mpWindowImpl->mpSysObj->Reparent(mpWindowImpl->mpFrame);
|
|
}
|
|
mpWindowImpl->mpFrameWindow = pWindow->mpWindowImpl->mpFrameWindow;
|
|
if ( pWindow->ImplIsOverlapWindow() )
|
|
mpWindowImpl->mpOverlapWindow = pWindow;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow = pWindow->mpWindowImpl->mpOverlapWindow;
|
|
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->ImplUpdateWindowPtr( pWindow );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
void Window::ImplUpdateWindowPtr()
|
|
{
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->ImplUpdateWindowPtr( this );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
void Window::ImplUpdateOverlapWindowPtr( bool bNewFrame )
|
|
{
|
|
bool bVisible = IsVisible();
|
|
Show( false );
|
|
ImplRemoveWindow( bNewFrame );
|
|
vcl::Window* pRealParent = mpWindowImpl->mpRealParent;
|
|
ImplInsertWindow( ImplGetParent() );
|
|
mpWindowImpl->mpRealParent = pRealParent;
|
|
ImplUpdateWindowPtr();
|
|
if ( ImplUpdatePos() )
|
|
ImplUpdateSysObjPos();
|
|
|
|
if ( bNewFrame )
|
|
{
|
|
vcl::Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow )
|
|
{
|
|
vcl::Window* pNextOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
|
|
pOverlapWindow = pNextOverlapWindow;
|
|
}
|
|
}
|
|
|
|
if ( bVisible )
|
|
Show();
|
|
}
|
|
|
|
SystemWindow* Window::GetSystemWindow() const
|
|
{
|
|
|
|
const vcl::Window* pWin = this;
|
|
while ( pWin && !pWin->IsSystemWindow() )
|
|
pWin = pWin->GetParent();
|
|
return static_cast<SystemWindow*>(const_cast<Window*>(pWin));
|
|
}
|
|
|
|
static SystemWindow *ImplGetLastSystemWindow( vcl::Window *pWin )
|
|
{
|
|
// get the most top-level system window, the one that contains the taskpanelist
|
|
SystemWindow *pSysWin = nullptr;
|
|
if( !pWin )
|
|
return pSysWin;
|
|
vcl::Window *pMyParent = pWin;
|
|
while ( pMyParent )
|
|
{
|
|
if ( pMyParent->IsSystemWindow() )
|
|
pSysWin = static_cast<SystemWindow*>(pMyParent);
|
|
pMyParent = pMyParent->GetParent();
|
|
}
|
|
return pSysWin;
|
|
}
|
|
|
|
void Window::SetParent( vcl::Window* pNewParent )
|
|
{
|
|
SAL_WARN_IF( !pNewParent, "vcl", "Window::SetParent(): pParent == NULL" );
|
|
SAL_WARN_IF( pNewParent == this, "vcl", "someone tried to reparent a window to itself" );
|
|
|
|
if( !pNewParent || pNewParent == this )
|
|
return;
|
|
|
|
// check if the taskpanelist would change and move the window pointer accordingly
|
|
SystemWindow *pSysWin = ImplGetLastSystemWindow(this);
|
|
SystemWindow *pNewSysWin = nullptr;
|
|
bool bChangeTaskPaneList = false;
|
|
if( pSysWin && pSysWin->ImplIsInTaskPaneList( this ) )
|
|
{
|
|
pNewSysWin = ImplGetLastSystemWindow( pNewParent );
|
|
if( pNewSysWin && pNewSysWin != pSysWin )
|
|
{
|
|
bChangeTaskPaneList = true;
|
|
pSysWin->GetTaskPaneList()->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 );
|
|
}
|
|
|
|
ImplSetFrameParent( pNewParent );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
mpWindowImpl->mpRealParent = pNewParent;
|
|
mpWindowImpl->mpBorderWindow->SetParent( pNewParent );
|
|
return;
|
|
}
|
|
|
|
if ( mpWindowImpl->mpParent.get() == pNewParent )
|
|
return;
|
|
|
|
if ( mpWindowImpl->mbFrame )
|
|
mpWindowImpl->mpFrame->SetParent( pNewParent->mpWindowImpl->mpFrame );
|
|
|
|
bool bVisible = IsVisible();
|
|
Show( false, ShowFlags::NoFocusChange );
|
|
|
|
// check if the overlap window changes
|
|
vcl::Window* pOldOverlapWindow;
|
|
vcl::Window* pNewOverlapWindow = nullptr;
|
|
if ( ImplIsOverlapWindow() )
|
|
pOldOverlapWindow = nullptr;
|
|
else
|
|
{
|
|
pNewOverlapWindow = pNewParent->ImplGetFirstOverlapWindow();
|
|
if ( mpWindowImpl->mpOverlapWindow.get() != pNewOverlapWindow )
|
|
pOldOverlapWindow = mpWindowImpl->mpOverlapWindow;
|
|
else
|
|
pOldOverlapWindow = nullptr;
|
|
}
|
|
|
|
// convert windows in the hierarchy
|
|
bool bFocusOverlapWin = HasChildPathFocus( true );
|
|
bool bFocusWin = HasChildPathFocus();
|
|
bool bNewFrame = pNewParent->mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow;
|
|
if ( bNewFrame )
|
|
{
|
|
if ( mpWindowImpl->mpFrameData->mpFocusWin )
|
|
{
|
|
if ( IsWindowOrChild( mpWindowImpl->mpFrameData->mpFocusWin ) )
|
|
mpWindowImpl->mpFrameData->mpFocusWin = nullptr;
|
|
}
|
|
if ( mpWindowImpl->mpFrameData->mpMouseMoveWin )
|
|
{
|
|
if ( IsWindowOrChild( mpWindowImpl->mpFrameData->mpMouseMoveWin ) )
|
|
mpWindowImpl->mpFrameData->mpMouseMoveWin = nullptr;
|
|
}
|
|
if ( mpWindowImpl->mpFrameData->mpMouseDownWin )
|
|
{
|
|
if ( IsWindowOrChild( mpWindowImpl->mpFrameData->mpMouseDownWin ) )
|
|
mpWindowImpl->mpFrameData->mpMouseDownWin = nullptr;
|
|
}
|
|
}
|
|
ImplRemoveWindow( bNewFrame );
|
|
ImplInsertWindow( pNewParent );
|
|
if ( mpWindowImpl->mnParentClipMode & ParentClipMode::Clip )
|
|
pNewParent->mpWindowImpl->mbClipChildren = true;
|
|
ImplUpdateWindowPtr();
|
|
if ( ImplUpdatePos() )
|
|
ImplUpdateSysObjPos();
|
|
|
|
// If the Overlap-Window has changed, we need to test whether
|
|
// OverlapWindows that had the Child window as their parent
|
|
// need to be put into the window hierarchy.
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
if ( bNewFrame )
|
|
{
|
|
vcl::Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow )
|
|
{
|
|
vcl::Window* pNextOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
|
|
pOverlapWindow = pNextOverlapWindow;
|
|
}
|
|
}
|
|
}
|
|
else if ( pOldOverlapWindow )
|
|
{
|
|
// reset Focus-Save
|
|
if ( bFocusWin ||
|
|
(pOldOverlapWindow->mpWindowImpl->mpLastFocusWindow &&
|
|
IsWindowOrChild( pOldOverlapWindow->mpWindowImpl->mpLastFocusWindow )) )
|
|
pOldOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
|
|
|
|
vcl::Window* pOverlapWindow = pOldOverlapWindow->mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow )
|
|
{
|
|
vcl::Window* pNextOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
if ( ImplIsRealParentPath( pOverlapWindow->ImplGetWindow() ) )
|
|
pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
|
|
pOverlapWindow = pNextOverlapWindow;
|
|
}
|
|
|
|
// update activate-status at next overlap window
|
|
if ( HasChildPathFocus( true ) )
|
|
ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow );
|
|
}
|
|
|
|
// also convert Activate-Status
|
|
if ( bNewFrame )
|
|
{
|
|
if ( (GetType() == WindowType::BORDERWINDOW) &&
|
|
(ImplGetWindow()->GetType() == WindowType::FLOATINGWINDOW) )
|
|
static_cast<ImplBorderWindow*>(this)->SetDisplayActive( mpWindowImpl->mpFrameData->mbHasFocus );
|
|
}
|
|
|
|
// when required give focus to new frame if
|
|
// FocusWindow is changed with SetParent()
|
|
if ( bFocusOverlapWin )
|
|
{
|
|
mpWindowImpl->mpFrameData->mpFocusWin = Application::GetFocusWindow();
|
|
if ( !mpWindowImpl->mpFrameData->mbHasFocus )
|
|
{
|
|
mpWindowImpl->mpFrame->ToTop( SalFrameToTop::NONE );
|
|
}
|
|
}
|
|
|
|
// Assure DragSource and DropTarget members are created
|
|
if ( bNewFrame )
|
|
{
|
|
GetDropTarget();
|
|
}
|
|
|
|
if( bChangeTaskPaneList )
|
|
pNewSysWin->GetTaskPaneList()->AddWindow( this );
|
|
|
|
if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
|
|
ImplGetOwnerDrawList().emplace_back(this );
|
|
|
|
if ( bVisible )
|
|
Show( true, ShowFlags::NoFocusChange | ShowFlags::NoActivate );
|
|
}
|
|
|
|
bool Window::IsAncestorOf( const vcl::Window& rWindow ) const
|
|
{
|
|
return ImplIsRealParentPath(&rWindow);
|
|
}
|
|
|
|
sal_uInt16 Window::GetChildCount() const
|
|
{
|
|
if (!mpWindowImpl)
|
|
return 0;
|
|
|
|
sal_uInt16 nChildCount = 0;
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
nChildCount++;
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
return nChildCount;
|
|
}
|
|
|
|
vcl::Window* Window::GetChild( sal_uInt16 nChild ) const
|
|
{
|
|
if (!mpWindowImpl)
|
|
return nullptr;
|
|
|
|
sal_uInt16 nChildCount = 0;
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
if ( nChild == nChildCount )
|
|
return pChild;
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
nChildCount++;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
vcl::Window* Window::GetWindow( GetWindowType nType ) const
|
|
{
|
|
if (!mpWindowImpl)
|
|
return nullptr;
|
|
|
|
switch ( nType )
|
|
{
|
|
case GetWindowType::Parent:
|
|
return mpWindowImpl->mpRealParent;
|
|
|
|
case GetWindowType::FirstChild:
|
|
return mpWindowImpl->mpFirstChild;
|
|
|
|
case GetWindowType::LastChild:
|
|
return mpWindowImpl->mpLastChild;
|
|
|
|
case GetWindowType::Prev:
|
|
return mpWindowImpl->mpPrev;
|
|
|
|
case GetWindowType::Next:
|
|
return mpWindowImpl->mpNext;
|
|
|
|
case GetWindowType::FirstOverlap:
|
|
return mpWindowImpl->mpFirstOverlap;
|
|
|
|
case GetWindowType::Overlap:
|
|
if ( ImplIsOverlapWindow() )
|
|
return const_cast<vcl::Window*>(this);
|
|
else
|
|
return mpWindowImpl->mpOverlapWindow;
|
|
|
|
case GetWindowType::ParentOverlap:
|
|
if ( ImplIsOverlapWindow() )
|
|
return mpWindowImpl->mpOverlapWindow;
|
|
else
|
|
return mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpOverlapWindow;
|
|
|
|
case GetWindowType::Client:
|
|
return this->ImplGetWindow();
|
|
|
|
case GetWindowType::RealParent:
|
|
return ImplGetParent();
|
|
|
|
case GetWindowType::Frame:
|
|
return mpWindowImpl->mpFrameWindow;
|
|
|
|
case GetWindowType::Border:
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
return mpWindowImpl->mpBorderWindow->GetWindow( GetWindowType::Border );
|
|
return const_cast<vcl::Window*>(this);
|
|
|
|
case GetWindowType::FirstTopWindowChild:
|
|
return ImplGetWinData()->maTopWindowChildren.empty() ? nullptr : (*ImplGetWinData()->maTopWindowChildren.begin()).get();
|
|
|
|
case GetWindowType::NextTopWindowSibling:
|
|
{
|
|
if ( !mpWindowImpl->mpRealParent )
|
|
return nullptr;
|
|
const ::std::list< VclPtr<vcl::Window> >& rTopWindows( mpWindowImpl->mpRealParent->ImplGetWinData()->maTopWindowChildren );
|
|
::std::list< VclPtr<vcl::Window> >::const_iterator myPos =
|
|
::std::find( rTopWindows.begin(), rTopWindows.end(), this );
|
|
if ( ( myPos == rTopWindows.end() ) || ( ++myPos == rTopWindows.end() ) )
|
|
return nullptr;
|
|
return *myPos;
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
bool Window::IsChild( const vcl::Window* pWindow ) const
|
|
{
|
|
do
|
|
{
|
|
if ( pWindow->ImplIsOverlapWindow() )
|
|
break;
|
|
|
|
pWindow = pWindow->ImplGetParent();
|
|
|
|
if ( pWindow == this )
|
|
return true;
|
|
}
|
|
while ( pWindow );
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Window::IsWindowOrChild( const vcl::Window* pWindow, bool bSystemWindow ) const
|
|
{
|
|
|
|
if ( this == pWindow )
|
|
return true;
|
|
return ImplIsChild( pWindow, bSystemWindow );
|
|
}
|
|
|
|
void Window::ImplSetFrameParent( const vcl::Window* pParent )
|
|
{
|
|
vcl::Window* pFrameWindow = ImplGetSVData()->maFrameData.mpFirstFrame;
|
|
while( pFrameWindow )
|
|
{
|
|
// search all frames that are children of this window
|
|
// and reparent them
|
|
if( ImplIsRealParentPath( pFrameWindow ) )
|
|
{
|
|
SAL_WARN_IF( mpWindowImpl->mpFrame == pFrameWindow->mpWindowImpl->mpFrame, "vcl", "SetFrameParent to own" );
|
|
SAL_WARN_IF( !mpWindowImpl->mpFrame, "vcl", "no frame" );
|
|
SalFrame* pParentFrame = pParent ? pParent->mpWindowImpl->mpFrame : nullptr;
|
|
pFrameWindow->mpWindowImpl->mpFrame->SetParent( pParentFrame );
|
|
}
|
|
pFrameWindow = pFrameWindow->mpWindowImpl->mpFrameData->mpNextFrame;
|
|
}
|
|
}
|
|
|
|
} /* namespace vcl */
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|