Currently we support DPI scaling by a integer factor. This commit changes that to percentage so we can have scaling factors like 1.5x or 1.25x. This is useful with 2.7k monitors that are in between standard DPI and HiDPI. Thresholding was adjusted to scale to 1.5x when DPI is between 120 and 168 DPI. The old method GetDPIScaleFactor has been changed to return a float value insted of int. Sometimes it is however more accurate to use GetDPIScalePercentage which was added in this commit. Change-Id: Iaecee793ff3d5084d00adeebbcf5d7368c580882 Reviewed-on: https://gerrit.libreoffice.org/30379 Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> Tested-by: Tomaž Vajngerl <quikee@gmail.com>
3749 lines
137 KiB
C++
3749 lines
137 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 <config_features.h>
|
|
#include <rtl/strbuf.hxx>
|
|
#include <tools/rc.h>
|
|
|
|
#include <sal/types.h>
|
|
#include <vcl/salgtype.hxx>
|
|
#include <vcl/event.hxx>
|
|
#include <vcl/help.hxx>
|
|
#include <vcl/cursor.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/window.hxx>
|
|
#include <vcl/syswin.hxx>
|
|
#include <vcl/syschild.hxx>
|
|
#include <vcl/dockwin.hxx>
|
|
#include <vcl/wall.hxx>
|
|
#include <vcl/fixed.hxx>
|
|
#include <vcl/gradient.hxx>
|
|
#include <vcl/button.hxx>
|
|
#include <vcl/taskpanelist.hxx>
|
|
#include <vcl/dialog.hxx>
|
|
#include <vcl/unowrap.hxx>
|
|
#include <vcl/gdimtf.hxx>
|
|
#include <vcl/lazydelete.hxx>
|
|
#include <vcl/virdev.hxx>
|
|
#include <vcl/settings.hxx>
|
|
#include <vcl/sysdata.hxx>
|
|
|
|
#include <vcl/uitest/uiobject.hxx>
|
|
#include <vcl/uitest/uitest.hxx>
|
|
|
|
#include <salframe.hxx>
|
|
#include <salobj.hxx>
|
|
#include <salinst.hxx>
|
|
#include <salgdi.hxx>
|
|
#include <svdata.hxx>
|
|
#include <window.h>
|
|
#include <toolbox.h>
|
|
#include <outdev.h>
|
|
#include <brdwin.hxx>
|
|
#include <helpwin.hxx>
|
|
#include "dndlistenercontainer.hxx"
|
|
|
|
#include <com/sun/star/awt/XDisplayConnection.hpp>
|
|
#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
|
|
#include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
|
|
#include <com/sun/star/rendering/CanvasFactory.hpp>
|
|
#include <com/sun/star/rendering/XSpriteCanvas.hpp>
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <unotools/configmgr.hxx>
|
|
|
|
#include <cassert>
|
|
#include <set>
|
|
#include <typeinfo>
|
|
|
|
#ifdef _WIN32 // see #140456#
|
|
#include <win/salframe.h>
|
|
#endif
|
|
|
|
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::lang;
|
|
using namespace ::com::sun::star::datatransfer::clipboard;
|
|
using namespace ::com::sun::star::datatransfer::dnd;
|
|
|
|
namespace vcl {
|
|
|
|
Window::Window( WindowType nType ) :
|
|
mpWindowImpl(new WindowImpl( nType ))
|
|
{
|
|
meOutDevType = OUTDEV_WINDOW;
|
|
|
|
// true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
|
|
mbEnableRTL = AllSettings::GetLayoutRTL();
|
|
}
|
|
|
|
Window::Window( vcl::Window* pParent, WinBits nStyle ) :
|
|
mpWindowImpl(new WindowImpl( WINDOW_WINDOW ))
|
|
{
|
|
meOutDevType = OUTDEV_WINDOW;
|
|
|
|
// true: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
|
|
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() == WINDOW_BORDERWINDOW ) {
|
|
pTempWin = pTempWin->GetWindow( GetWindowType::FirstChild );
|
|
}
|
|
// check if pTempWin is not null, otherwise use the
|
|
// original address
|
|
if ( pTempWin ) {
|
|
pWindow = pTempWin;
|
|
}
|
|
|
|
OStringBuffer aErrorString;
|
|
aErrorString.append(' ');
|
|
aErrorString.append(typeid( *pWindow ).name());
|
|
aErrorString.append("(");
|
|
aErrorString.append(
|
|
OUStringToOString(
|
|
pWindow->GetText(),
|
|
RTL_TEXTENCODING_UTF8
|
|
)
|
|
);
|
|
aErrorString.append(")");
|
|
return aErrorString.makeStringAndClear();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
bool Window::IsDisposed() const
|
|
{
|
|
return !mpWindowImpl;
|
|
}
|
|
|
|
void Window::dispose()
|
|
{
|
|
assert( mpWindowImpl );
|
|
assert( !mpWindowImpl->mbInDispose ); // should only be called from disposeOnce()
|
|
assert( (!mpWindowImpl->mpParent ||
|
|
!mpWindowImpl->mpParent->IsDisposed()) &&
|
|
"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.
|
|
Reference< css::rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
|
|
if( xCanvas.is() )
|
|
{
|
|
Reference < XComponent > xCanvasComponent( xCanvas, UNO_QUERY );
|
|
if( xCanvasComponent.is() )
|
|
xCanvasComponent->dispose();
|
|
}
|
|
|
|
mpWindowImpl->mbInDispose = true;
|
|
|
|
CallEventListeners( VCLEVENT_OBJECT_DYING );
|
|
|
|
// do not send child events for frames that were registered as native frames
|
|
if( !ImplIsAccessibleNativeFrame() && mpWindowImpl->mbReallyVisible )
|
|
if ( ImplIsAccessibleCandidate() && GetAccessibleParentWindow() )
|
|
GetAccessibleParentWindow()->CallEventListeners( VCLEVENT_WINDOW_CHILDDESTROYED, 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
|
|
Reference < XComponent > xDnDComponent( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY );
|
|
|
|
if( xDnDComponent.is() )
|
|
xDnDComponent->dispose();
|
|
|
|
if( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
|
|
{
|
|
try
|
|
{
|
|
// deregister drop target listener
|
|
if( mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
|
|
{
|
|
Reference< XDragGestureRecognizer > xDragGestureRecognizer =
|
|
Reference< XDragGestureRecognizer > (mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
|
|
if( xDragGestureRecognizer.is() )
|
|
{
|
|
xDragGestureRecognizer->removeDragGestureListener(
|
|
Reference< XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY));
|
|
}
|
|
|
|
mpWindowImpl->mpFrameData->mxDropTarget->removeDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
|
|
mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
|
|
}
|
|
|
|
// 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 = Application::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();
|
|
}
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
|
|
if ( pSVData->maHelpData.mpHelpWin && (pSVData->maHelpData.mpHelpWin->GetParent() == this) )
|
|
ImplDestroyHelpWindow( true );
|
|
|
|
SAL_WARN_IF( pSVData->maWinData.mpTrackWin.get() == this, "vcl",
|
|
"Window::~Window(): Window is in TrackingMode" );
|
|
SAL_WARN_IF(IsMouseCaptured(), "vcl",
|
|
"Window::~Window(): Window has the mouse captured");
|
|
|
|
// due to old compatibility
|
|
if ( pSVData->maWinData.mpTrackWin == this )
|
|
EndTracking();
|
|
if (IsMouseCaptured())
|
|
ReleaseMouse();
|
|
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
if ( true ) // always perform these tests in debug builds
|
|
{
|
|
OStringBuffer aErrorStr;
|
|
bool bError = false;
|
|
vcl::Window* pTempWin;
|
|
|
|
if ( mpWindowImpl->mpFirstChild )
|
|
{
|
|
OStringBuffer aTempStr("Window (");
|
|
aTempStr.append(lcl_createWindowInfo(this));
|
|
aTempStr.append(") with live children destroyed: ");
|
|
pTempWin = mpWindowImpl->mpFirstChild;
|
|
while ( pTempWin )
|
|
{
|
|
aTempStr.append(lcl_createWindowInfo(pTempWin));
|
|
pTempWin = pTempWin->mpWindowImpl->mpNext;
|
|
}
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
|
|
}
|
|
|
|
if (mpWindowImpl->mpFrameData != nullptr)
|
|
{
|
|
pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap;
|
|
while ( pTempWin )
|
|
{
|
|
if ( ImplIsRealParentPath( pTempWin ) )
|
|
{
|
|
bError = true;
|
|
aErrorStr.append(lcl_createWindowInfo(pTempWin));
|
|
}
|
|
pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
|
|
}
|
|
if ( bError )
|
|
{
|
|
OStringBuffer aTempStr;
|
|
aTempStr.append("Window (");
|
|
aTempStr.append(lcl_createWindowInfo(this));
|
|
aTempStr.append(") with live SystemWindows destroyed: ");
|
|
aTempStr.append(aErrorStr.toString());
|
|
OSL_FAIL(aTempStr.getStr());
|
|
// abort in debug builds, must be fixed!
|
|
Application::Abort(OStringToOUString(
|
|
aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
|
|
}
|
|
}
|
|
|
|
bError = false;
|
|
pTempWin = pSVData->maWinData.mpFirstFrame;
|
|
while ( pTempWin )
|
|
{
|
|
if ( ImplIsRealParentPath( pTempWin ) )
|
|
{
|
|
bError = true;
|
|
aErrorStr.append(lcl_createWindowInfo(pTempWin));
|
|
}
|
|
pTempWin = pTempWin->mpWindowImpl->mpFrameData->mpNextFrame;
|
|
}
|
|
if ( bError )
|
|
{
|
|
OStringBuffer aTempStr( "Window (" );
|
|
aTempStr.append(lcl_createWindowInfo(this));
|
|
aTempStr.append(") with live SystemWindows destroyed: ");
|
|
aTempStr.append(aErrorStr.toString());
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
|
|
}
|
|
|
|
if ( mpWindowImpl->mpFirstOverlap )
|
|
{
|
|
OStringBuffer aTempStr("Window (");
|
|
aTempStr.append(lcl_createWindowInfo(this));
|
|
aTempStr.append(") with live SystemWindows destroyed: ");
|
|
pTempWin = mpWindowImpl->mpFirstOverlap;
|
|
while ( pTempWin )
|
|
{
|
|
aTempStr.append(lcl_createWindowInfo(pTempWin));
|
|
pTempWin = pTempWin->mpWindowImpl->mpNext;
|
|
}
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
|
|
}
|
|
|
|
vcl::Window* pMyParent = GetParent();
|
|
SystemWindow* pMySysWin = nullptr;
|
|
|
|
while ( pMyParent )
|
|
{
|
|
if ( pMyParent->IsSystemWindow() )
|
|
{
|
|
pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
|
|
}
|
|
pMyParent = pMyParent->GetParent();
|
|
}
|
|
if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
|
|
{
|
|
OStringBuffer aTempStr("Window (");
|
|
aTempStr.append(lcl_createWindowInfo(this));
|
|
aTempStr.append(") still in TaskPanelList!");
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in debug builds, this must be fixed!
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if( mpWindowImpl->mbIsInTaskPaneList )
|
|
{
|
|
vcl::Window* pMyParent = GetParent();
|
|
SystemWindow* pMySysWin = nullptr;
|
|
|
|
while ( pMyParent )
|
|
{
|
|
if ( pMyParent->IsSystemWindow() )
|
|
{
|
|
pMySysWin = dynamic_cast<SystemWindow *>(pMyParent);
|
|
}
|
|
pMyParent = pMyParent->GetParent();
|
|
}
|
|
if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
|
|
{
|
|
pMySysWin->GetTaskPaneList()->RemoveWindow( this );
|
|
}
|
|
else
|
|
{
|
|
OStringBuffer aTempStr("Window (");
|
|
aTempStr.append(OUStringToOString(GetText(), RTL_TEXTENCODING_UTF8));
|
|
aTempStr.append(") not found in TaskPanelList!");
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
}
|
|
}
|
|
|
|
// remove from size-group if necessary
|
|
remove_from_all_size_groups();
|
|
|
|
// clear mnemonic labels
|
|
std::vector<VclPtr<FixedText> > aMnemonicLabels(list_mnemonic_labels());
|
|
for (auto aI = aMnemonicLabels.begin(); aI != aMnemonicLabels.end(); ++aI)
|
|
{
|
|
remove_mnemonic_label(*aI);
|
|
}
|
|
|
|
// hide window in order to trigger the Paint-Handling
|
|
Hide();
|
|
|
|
// announce the window is to be destroyed
|
|
{
|
|
NotifyEvent aNEvt( MouseNotifyEvent::DESTROY, this );
|
|
CompatNotify( aNEvt );
|
|
}
|
|
|
|
// EndExtTextInputMode
|
|
if ( pSVData->maWinData.mpExtTextInputWin == this )
|
|
{
|
|
EndExtTextInput();
|
|
if ( pSVData->maWinData.mpExtTextInputWin == this )
|
|
pSVData->maWinData.mpExtTextInputWin = nullptr;
|
|
}
|
|
|
|
// check if the focus window is our child
|
|
bool bHasFocussedChild = false;
|
|
if( pSVData->maWinData.mpFocusWin && ImplIsRealParentPath( pSVData->maWinData.mpFocusWin ) )
|
|
{
|
|
// #122232#, this must not happen and is an application bug ! but we try some cleanup to hopefully avoid crashes, see below
|
|
bHasFocussedChild = true;
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
OStringBuffer aTempStr("Window (");
|
|
aTempStr.append(OUStringToOString(GetText(),
|
|
RTL_TEXTENCODING_UTF8)).
|
|
append(") with focussed child window destroyed ! THIS WILL LEAD TO CRASHES AND MUST BE FIXED !");
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
Application::Abort(OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8 )); // abort in debug build version, this must be fixed!
|
|
#endif
|
|
}
|
|
|
|
// if we get focus pass focus to another window
|
|
vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow();
|
|
if ( pSVData->maWinData.mpFocusWin == this
|
|
|| bHasFocussedChild ) // #122232#, see above, try some cleanup
|
|
{
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
pSVData->maWinData.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;
|
|
}
|
|
else if ( ImplIsOverlapWindow() )
|
|
pParent = mpWindowImpl->mpOverlapWindow;
|
|
|
|
if ( pParent && pParent->IsEnabled() && pParent->IsInputEnabled() && ! pParent->IsInModalMode() )
|
|
pParent->GrabFocus();
|
|
else
|
|
mpWindowImpl->mpFrameWindow->GrabFocus();
|
|
|
|
// If the focus was set back to 'this' set it to nothing
|
|
if ( pSVData->maWinData.mpFocusWin == this )
|
|
{
|
|
pSVData->maWinData.mpFocusWin = nullptr;
|
|
pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( pOverlapWindow != nullptr &&
|
|
pOverlapWindow->mpWindowImpl->mpLastFocusWindow == this )
|
|
pOverlapWindow->mpWindowImpl->mpLastFocusWindow = nullptr;
|
|
|
|
// reset hint for DefModalDialogParent
|
|
if( pSVData->maWinData.mpActiveApplicationFrame == this )
|
|
pSVData->maWinData.mpActiveApplicationFrame = nullptr;
|
|
|
|
// reset hint of what was the last wheeled window
|
|
if( pSVData->maWinData.mpLastWheelWindow == this )
|
|
pSVData->maWinData.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->maWinData.mpLastDeacWin == this )
|
|
pSVData->maWinData.mpLastDeacWin = nullptr;
|
|
|
|
if ( 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;
|
|
}
|
|
|
|
// release SalGraphics
|
|
OutputDevice *pOutDev = GetOutDev();
|
|
pOutDev->ReleaseGraphics();
|
|
|
|
// 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: inconsistency in top window chain!" );
|
|
if ( myPos != pParentWinData->maTopWindowChildren.end() )
|
|
pParentWinData->maTopWindowChildren.erase( myPos );
|
|
}
|
|
}
|
|
|
|
delete mpWindowImpl->mpWinData;
|
|
|
|
// remove BorderWindow or Frame window data
|
|
mpWindowImpl->mpBorderWindow.disposeAndClear();
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
if ( pSVData->maWinData.mpFirstFrame == this )
|
|
pSVData->maWinData.mpFirstFrame = mpWindowImpl->mpFrameData->mpNextFrame;
|
|
else
|
|
{
|
|
vcl::Window* pSysWin = pSVData->maWinData.mpFirstFrame;
|
|
while ( pSysWin->mpWindowImpl->mpFrameData->mpNextFrame.get() != this )
|
|
pSysWin = pSysWin->mpWindowImpl->mpFrameData->mpNextFrame;
|
|
|
|
assert (mpWindowImpl->mpFrameData->mpNextFrame.get() != pSysWin);
|
|
pSysWin->mpWindowImpl->mpFrameData->mpNextFrame = mpWindowImpl->mpFrameData->mpNextFrame;
|
|
}
|
|
mpWindowImpl->mpFrame->SetCallback( nullptr, nullptr );
|
|
pSVData->mpDefInst->DestroyFrame( mpWindowImpl->mpFrame );
|
|
assert (mpWindowImpl->mpFrameData->mnFocusId == nullptr);
|
|
assert (mpWindowImpl->mpFrameData->mnMouseMoveId == nullptr);
|
|
delete mpWindowImpl->mpFrameData;
|
|
}
|
|
|
|
// should be the last statements
|
|
mpWindowImpl.reset();
|
|
|
|
OutputDevice::dispose();
|
|
}
|
|
|
|
Window::~Window()
|
|
{
|
|
// FIXME: we should kill all LazyDeletor usage.
|
|
vcl::LazyDeletor::Undelete( this );
|
|
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.
|
|
|
|
::OutputDevice const* Window::GetOutDev() const
|
|
{
|
|
return this;
|
|
}
|
|
|
|
::OutputDevice* Window::GetOutDev()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
} /* namespace vcl */
|
|
|
|
WindowImpl::WindowImpl( WindowType nType )
|
|
{
|
|
maZoom = Fraction( 1, 1 );
|
|
maWinRegion = vcl::Region(true);
|
|
maWinClipRegion = vcl::Region(true);
|
|
mpWinData = nullptr; // Extra Window Data, that we don't need for all windows
|
|
mpFrameData = nullptr; // Frame Data
|
|
mpFrame = nullptr; // Pointer to frame window
|
|
mpSysObj = nullptr;
|
|
mpFrameWindow = nullptr; // window to top level parent (same as frame window)
|
|
mpOverlapWindow = nullptr; // first overlap parent
|
|
mpBorderWindow = nullptr; // Border-Window
|
|
mpClientWindow = nullptr; // Client-Window of a FrameWindow
|
|
mpParent = nullptr; // parent (incl. BorderWindow)
|
|
mpRealParent = nullptr; // real parent (excl. BorderWindow)
|
|
mpFirstChild = nullptr; // first child window
|
|
mpLastChild = nullptr; // last child window
|
|
mpFirstOverlap = nullptr; // first overlap window (only set in overlap windows)
|
|
mpLastOverlap = nullptr; // last overlap window (only set in overlap windows)
|
|
mpPrev = nullptr; // prev window
|
|
mpNext = nullptr; // next window
|
|
mpNextOverlap = nullptr; // next overlap window of frame
|
|
mpLastFocusWindow = nullptr; // window for focus restore
|
|
mpDlgCtrlDownWindow = nullptr; // window for dialog control
|
|
mnEventListenersIteratingCount = 0;
|
|
mnChildEventListenersIteratingCount = 0;
|
|
mpCursor = nullptr; // cursor
|
|
mpControlFont = nullptr; // font properties
|
|
mpVCLXWindow = nullptr;
|
|
mpAccessibleInfos = nullptr;
|
|
maControlForeground = Color( COL_TRANSPARENT ); // no foreground set
|
|
maControlBackground = Color( COL_TRANSPARENT ); // no background set
|
|
mnLeftBorder = 0; // left border
|
|
mnTopBorder = 0; // top border
|
|
mnRightBorder = 0; // right border
|
|
mnBottomBorder = 0; // bottom border
|
|
mnWidthRequest = -1; // width request
|
|
mnHeightRequest = -1; // height request
|
|
mnOptimalWidthCache = -1; // optimal width cache
|
|
mnOptimalHeightCache = -1; // optimal height cache
|
|
mnX = 0; // X-Position to Parent
|
|
mnY = 0; // Y-Position to Parent
|
|
mnAbsScreenX = 0; // absolute X-position on screen, used for RTL window positioning
|
|
mpChildClipRegion = nullptr; // Child-Clip-Region when ClipChildren
|
|
mpPaintRegion = nullptr; // Paint-ClipRegion
|
|
mnStyle = 0; // style (init in ImplInitWindow)
|
|
mnPrevStyle = 0; // prevstyle (set in SetStyle)
|
|
mnExtendedStyle = 0; // extended style (init in ImplInitWindow)
|
|
mnPrevExtendedStyle = 0; // prevstyle (set in SetExtendedStyle)
|
|
mnType = nType; // type
|
|
mnGetFocusFlags = GetFocusFlags::NONE; // Flags fuer GetFocus()-Aufruf
|
|
mnWaitCount = 0; // Wait-Count (>1 == Warte-MousePointer)
|
|
mnPaintFlags = 0; // Flags for ImplCallPaint
|
|
mnParentClipMode = ParentClipMode::NONE; // Flags for Parent-ClipChildren-Mode
|
|
mnActivateMode = ActivateModeFlags::NONE; // Will be converted in System/Overlap-Windows
|
|
mnDlgCtrlFlags = DialogControlFlags::NONE; // DialogControl-Flags
|
|
mnLockCount = 0; // LockCount
|
|
meAlwaysInputMode = AlwaysInputNone; // neither AlwaysEnableInput nor AlwaysDisableInput called
|
|
meHalign = VclAlign::Fill;
|
|
meValign = VclAlign::Fill;
|
|
mePackType = VclPackType::Start;
|
|
mnPadding = 0;
|
|
mnGridHeight = 1;
|
|
mnGridLeftAttach = -1;
|
|
mnGridTopAttach = -1;
|
|
mnGridWidth = 1;
|
|
mnBorderWidth = 0;
|
|
mnMarginLeft = 0;
|
|
mnMarginRight = 0;
|
|
mnMarginTop = 0;
|
|
mnMarginBottom = 0;
|
|
mbFrame = false; // true: Window is a frame window
|
|
mbBorderWin = false; // true: Window is a border window
|
|
mbOverlapWin = false; // true: Window is a overlap window
|
|
mbSysWin = false; // true: SystemWindow is the base class
|
|
mbDialog = false; // true: Dialog is the base class
|
|
mbDockWin = false; // true: DockingWindow is the base class
|
|
mbFloatWin = false; // true: FloatingWindow is the base class
|
|
mbPushButton = false; // true: PushButton is the base class
|
|
mbToolBox = false; // true: ToolBox is the base class
|
|
mbMenuFloatingWindow = false; // true: MenuFloatingWindow is the base class
|
|
mbToolbarFloatingWindow = false; // true: ImplPopupFloatWin is the base class, used for subtoolbars
|
|
mbSplitter = false; // true: Splitter is the base class
|
|
mbVisible = false; // true: Show( true ) called
|
|
mbOverlapVisible = false; // true: Hide called for visible window from ImplHideAllOverlapWindow()
|
|
mbDisabled = false; // true: Enable( false ) called
|
|
mbInputDisabled = false; // true: EnableInput( false ) called
|
|
mbNoUpdate = false; // true: SetUpdateMode( false ) called
|
|
mbNoParentUpdate = false; // true: SetParentUpdateMode( false ) called
|
|
mbActive = false; // true: Window Active
|
|
mbReallyVisible = false; // true: this and all parents to an overlapped window are visible
|
|
mbReallyShown = false; // true: this and all parents to an overlapped window are shown
|
|
mbInInitShow = false; // true: we are in InitShow
|
|
mbChildPtrOverwrite = false; // true: PointerStyle overwrites Child-Pointer
|
|
mbNoPtrVisible = false; // true: ShowPointer( false ) called
|
|
mbMouseMove = false; // true: BaseMouseMove called
|
|
mbPaintFrame = false; // true: Paint is visible, but not painted
|
|
mbInPaint = false; // true: Inside PaintHdl
|
|
mbMouseButtonDown = false; // true: BaseMouseButtonDown called
|
|
mbMouseButtonUp = false; // true: BaseMouseButtonUp called
|
|
mbKeyInput = false; // true: BaseKeyInput called
|
|
mbKeyUp = false; // true: BaseKeyUp called
|
|
mbCommand = false; // true: BaseCommand called
|
|
mbDefPos = true; // true: Position is not Set
|
|
mbDefSize = true; // true: Size is not Set
|
|
mbCallMove = true; // true: Move must be called by Show
|
|
mbCallResize = true; // true: Resize must be called by Show
|
|
mbWaitSystemResize = true; // true: Wait for System-Resize
|
|
mbInitWinClipRegion = true; // true: Calc Window Clip Region
|
|
mbInitChildRegion = false; // true: InitChildClipRegion
|
|
mbWinRegion = false; // true: Window Region
|
|
mbClipChildren = false; // true: Child-window should be clipped
|
|
mbClipSiblings = false; // true: Adjacent Child-window should be clipped
|
|
mbChildTransparent = false; // true: Child-windows are allowed to switch to transparent (incl. Parent-CLIPCHILDREN)
|
|
mbPaintTransparent = false; // true: Paints should be executed on the Parent
|
|
mbMouseTransparent = false; // true: Window is transparent for Mouse
|
|
mbDlgCtrlStart = false; // true: From here on own Dialog-Control
|
|
mbFocusVisible = false; // true: Focus Visible
|
|
mbUseNativeFocus = false;
|
|
mbNativeFocusVisible = false; // true: native Focus Visible
|
|
mbInShowFocus = false; // prevent recursion
|
|
mbInHideFocus = false; // prevent recursion
|
|
mbTrackVisible = false; // true: Tracking Visible
|
|
mbControlForeground = false; // true: Foreground-Property set
|
|
mbControlBackground = false; // true: Background-Property set
|
|
mbAlwaysOnTop = false; // true: always visible for all others windows
|
|
mbCompoundControl = false; // true: Composite Control => Listener...
|
|
mbCompoundControlHasFocus = false; // true: Composite Control has focus somewhere
|
|
mbPaintDisabled = false; // true: Paint should not be executed
|
|
mbAllResize = false; // true: Also sent ResizeEvents with 0,0
|
|
mbInDispose = false; // true: We're still in Window::dispose()
|
|
mbExtTextInput = false; // true: ExtTextInput-Mode is active
|
|
mbInFocusHdl = false; // true: Within GetFocus-Handler
|
|
mbCreatedWithToolkit = false;
|
|
mbSuppressAccessibilityEvents = false; // true: do not send any accessibility events
|
|
mbDrawSelectionBackground = false; // true: draws transparent window background to indicate (toolbox) selection
|
|
mbIsInTaskPaneList = false; // true: window was added to the taskpanelist in the topmost system window
|
|
mnNativeBackground = ControlPart::NONE; // initialize later, depends on type
|
|
mbCallHandlersDuringInputDisabled = false; // true: call event handlers even if input is disabled
|
|
mbHelpTextDynamic = false; // true: append help id in HELP_DEBUG case
|
|
mbFakeFocusSet = false; // true: pretend as if the window has focus.
|
|
mbHexpand = false;
|
|
mbVexpand = false;
|
|
mbExpand = false;
|
|
mbFill = true;
|
|
mbSecondary = false;
|
|
mbNonHomogeneous = false;
|
|
static bool bDoubleBuffer = getenv("VCL_DOUBLEBUFFERING_FORCE_ENABLE");
|
|
mbDoubleBufferingRequested = bDoubleBuffer; // when we are not sure, assume it cannot do double-buffering via RenderContext
|
|
}
|
|
|
|
WindowImpl::~WindowImpl()
|
|
{
|
|
delete mpChildClipRegion;
|
|
delete mpAccessibleInfos;
|
|
delete mpControlFont;
|
|
}
|
|
|
|
ImplWinData::ImplWinData() :
|
|
mpExtOldText(nullptr),
|
|
mpExtOldAttrAry(nullptr),
|
|
mpCursorRect(nullptr),
|
|
mnCursorExtWidth(0),
|
|
mbVertical(false),
|
|
mpCompositionCharRects(nullptr),
|
|
mnCompositionCharRects(0),
|
|
mpFocusRect(nullptr),
|
|
mpTrackRect(nullptr),
|
|
mnTrackFlags(ShowTrackFlags::NONE),
|
|
mnIsTopWindow((sal_uInt16) ~0), // not initialized yet, 0/1 will indicate TopWindow (see IsTopWindow())
|
|
mbMouseOver(false),
|
|
mbEnableNativeWidget(false)
|
|
{
|
|
}
|
|
|
|
ImplWinData::~ImplWinData()
|
|
{
|
|
delete mpExtOldText;
|
|
delete mpExtOldAttrAry;
|
|
delete mpCursorRect;
|
|
delete[] mpCompositionCharRects;
|
|
delete mpFocusRect;
|
|
delete mpTrackRect;
|
|
}
|
|
|
|
|
|
namespace vcl {
|
|
|
|
bool Window::AcquireGraphics() const
|
|
{
|
|
DBG_TESTSOLARMUTEX();
|
|
|
|
if ( mpGraphics )
|
|
return true;
|
|
|
|
mbInitLineColor = true;
|
|
mbInitFillColor = true;
|
|
mbInitFont = true;
|
|
mbInitTextColor = true;
|
|
mbInitClipRegion = true;
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
|
|
mpGraphics = mpWindowImpl->mpFrame->AcquireGraphics();
|
|
// try harder if no wingraphics was available directly
|
|
if ( !mpGraphics )
|
|
{
|
|
// find another output device in the same frame
|
|
OutputDevice* pReleaseOutDev = pSVData->maGDIData.mpLastWinGraphics;
|
|
while ( pReleaseOutDev )
|
|
{
|
|
if ( static_cast<vcl::Window*>(pReleaseOutDev)->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame )
|
|
break;
|
|
pReleaseOutDev = pReleaseOutDev->mpPrevGraphics;
|
|
}
|
|
|
|
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 = mpWindowImpl->mpFrame->AcquireGraphics();
|
|
}
|
|
}
|
|
}
|
|
|
|
// update global LRU list of wingraphics
|
|
if ( mpGraphics )
|
|
{
|
|
mpNextGraphics = pSVData->maGDIData.mpFirstWinGraphics;
|
|
pSVData->maGDIData.mpFirstWinGraphics = const_cast<vcl::Window*>(this);
|
|
if ( mpNextGraphics )
|
|
mpNextGraphics->mpPrevGraphics = const_cast<vcl::Window*>(this);
|
|
if ( !pSVData->maGDIData.mpLastWinGraphics )
|
|
pSVData->maGDIData.mpLastWinGraphics = const_cast<vcl::Window*>(this);
|
|
}
|
|
|
|
if ( mpGraphics )
|
|
{
|
|
mpGraphics->SetXORMode( (RasterOp::Invert == meRasterOp) || (RasterOp::Xor == meRasterOp) );
|
|
mpGraphics->setAntiAliasB2DDraw(bool(mnAntialiasing & AntialiasingFlags::EnableB2dDraw));
|
|
}
|
|
|
|
return mpGraphics != nullptr;
|
|
}
|
|
|
|
void Window::ReleaseGraphics( bool bRelease )
|
|
{
|
|
DBG_TESTSOLARMUTEX();
|
|
|
|
if ( !mpGraphics )
|
|
return;
|
|
|
|
// release the fonts of the physically released graphics device
|
|
if( bRelease )
|
|
ImplReleaseFonts();
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
|
|
vcl::Window* pWindow = this;
|
|
|
|
if ( bRelease )
|
|
pWindow->mpWindowImpl->mpFrame->ReleaseGraphics( mpGraphics );
|
|
// remove from global LRU list of window graphics
|
|
if ( mpPrevGraphics )
|
|
mpPrevGraphics->mpNextGraphics = mpNextGraphics;
|
|
else
|
|
pSVData->maGDIData.mpFirstWinGraphics = mpNextGraphics;
|
|
if ( mpNextGraphics )
|
|
mpNextGraphics->mpPrevGraphics = mpPrevGraphics;
|
|
else
|
|
pSVData->maGDIData.mpLastWinGraphics = mpPrevGraphics;
|
|
|
|
mpGraphics = nullptr;
|
|
mpPrevGraphics = nullptr;
|
|
mpNextGraphics = nullptr;
|
|
}
|
|
|
|
static sal_Int32 CountDPIScaleFactor(sal_Int32 nDPI)
|
|
{
|
|
sal_Int32 nResult = 100;
|
|
|
|
#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 hi-dpi to greater than 168
|
|
if (nDPI > 216) // 96 * 2 + 96 / 4
|
|
nResult = 250;
|
|
else if (nDPI > 168) // 96 * 2 - 96 / 4
|
|
nResult = 200;
|
|
else if (nDPI > 120) // 96 * 1.5 - 96 / 4
|
|
nResult = 150;
|
|
#else
|
|
(void)nDPI;
|
|
#endif
|
|
|
|
return nResult;
|
|
}
|
|
|
|
void Window::ImplInit( vcl::Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
|
|
{
|
|
SAL_WARN_IF( !mpWindowImpl->mbFrame && !pParent && GetType() != WINDOW_FIXEDIMAGE, "vcl",
|
|
"Window::Window(): pParent == NULL" );
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
vcl::Window* pRealParent = pParent;
|
|
|
|
// inherit 3D look
|
|
if ( !mpWindowImpl->mbOverlapWin && pParent && (pParent->GetStyle() & WB_3DLOOK) )
|
|
nStyle |= WB_3DLOOK;
|
|
|
|
// create border window if necessary
|
|
if ( !mpWindowImpl->mbFrame && !mpWindowImpl->mbBorderWin && !mpWindowImpl->mpBorderWindow
|
|
&& (nStyle & (WB_BORDER | WB_SYSTEMCHILDWINDOW) ) )
|
|
{
|
|
BorderWindowStyle nBorderTypeStyle = BorderWindowStyle::NONE;
|
|
if( (nStyle & WB_SYSTEMCHILDWINDOW) )
|
|
{
|
|
// handle WB_SYSTEMCHILDWINDOW
|
|
// these should be analogous to a top level frame; meaning they
|
|
// should have a border window with style BorderWindowStyle::Frame
|
|
// which controls their size
|
|
nBorderTypeStyle |= BorderWindowStyle::Frame;
|
|
nStyle |= WB_BORDER;
|
|
}
|
|
VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL), nBorderTypeStyle );
|
|
static_cast<vcl::Window*>(pBorderWin)->mpWindowImpl->mpClientWindow = this;
|
|
pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
|
|
mpWindowImpl->mpBorderWindow = pBorderWin;
|
|
pParent = mpWindowImpl->mpBorderWindow;
|
|
}
|
|
else if( !mpWindowImpl->mbFrame && ! pParent )
|
|
{
|
|
mpWindowImpl->mbOverlapWin = true;
|
|
mpWindowImpl->mbFrame = true;
|
|
}
|
|
|
|
// insert window in list
|
|
ImplInsertWindow( pParent );
|
|
mpWindowImpl->mnStyle = nStyle;
|
|
|
|
if( pParent && ! mpWindowImpl->mbFrame )
|
|
mbEnableRTL = AllSettings::GetLayoutRTL();
|
|
|
|
// test for frame creation
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
// create frame
|
|
SalFrameStyleFlags nFrameStyle = SalFrameStyleFlags::NONE;
|
|
|
|
if ( nStyle & WB_MOVEABLE )
|
|
nFrameStyle |= SalFrameStyleFlags::MOVEABLE;
|
|
if ( nStyle & WB_SIZEABLE )
|
|
nFrameStyle |= SalFrameStyleFlags::SIZEABLE;
|
|
if ( nStyle & WB_CLOSEABLE )
|
|
nFrameStyle |= SalFrameStyleFlags::CLOSEABLE;
|
|
if ( nStyle & WB_APP )
|
|
nFrameStyle |= SalFrameStyleFlags::DEFAULT;
|
|
// check for undecorated floating window
|
|
if( // 1. floating windows that are not moveable/sizeable (only closeable allowed)
|
|
( !(nFrameStyle & ~SalFrameStyleFlags::CLOSEABLE) &&
|
|
( mpWindowImpl->mbFloatWin || ((GetType() == WINDOW_BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow) || (nStyle & WB_SYSTEMFLOATWIN) ) ) ||
|
|
// 2. borderwindows of floaters with ownerdraw decoration
|
|
( ((GetType() == WINDOW_BORDERWINDOW) && static_cast<ImplBorderWindow*>(this)->mbFloatWindow && (nStyle & WB_OWNERDRAWDECORATION) ) ) )
|
|
{
|
|
nFrameStyle = SalFrameStyleFlags::FLOAT;
|
|
if( nStyle & WB_OWNERDRAWDECORATION )
|
|
nFrameStyle |= (SalFrameStyleFlags::OWNERDRAWDECORATION | SalFrameStyleFlags::NOSHADOW);
|
|
}
|
|
else if( mpWindowImpl->mbFloatWin )
|
|
nFrameStyle |= SalFrameStyleFlags::TOOLWINDOW;
|
|
|
|
if( nStyle & WB_INTROWIN )
|
|
nFrameStyle |= SalFrameStyleFlags::INTRO;
|
|
if( nStyle & WB_TOOLTIPWIN )
|
|
nFrameStyle |= SalFrameStyleFlags::TOOLTIP;
|
|
|
|
if( nStyle & WB_NOSHADOW )
|
|
nFrameStyle |= SalFrameStyleFlags::NOSHADOW;
|
|
|
|
if( nStyle & WB_SYSTEMCHILDWINDOW )
|
|
nFrameStyle |= SalFrameStyleFlags::SYSTEMCHILD;
|
|
|
|
switch (mpWindowImpl->mnType)
|
|
{
|
|
case WINDOW_DIALOG:
|
|
case WINDOW_TABDIALOG:
|
|
case WINDOW_MODALDIALOG:
|
|
case WINDOW_MODELESSDIALOG:
|
|
case WINDOW_MESSBOX:
|
|
case WINDOW_INFOBOX:
|
|
case WINDOW_WARNINGBOX:
|
|
case WINDOW_ERRORBOX:
|
|
case WINDOW_QUERYBOX:
|
|
nFrameStyle |= SalFrameStyleFlags::DIALOG;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
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(
|
|
"Could not create system window!",
|
|
Reference< XInterface >() );
|
|
}
|
|
|
|
pFrame->SetCallback( this, ImplWindowFrameProc );
|
|
|
|
// set window frame data
|
|
mpWindowImpl->mpFrameData = new ImplFrameData;
|
|
mpWindowImpl->mpFrame = pFrame;
|
|
mpWindowImpl->mpFrameWindow = this;
|
|
mpWindowImpl->mpOverlapWindow = this;
|
|
|
|
// set frame data
|
|
assert (pSVData->maWinData.mpFirstFrame.get() != this);
|
|
mpWindowImpl->mpFrameData->mpNextFrame = pSVData->maWinData.mpFirstFrame;
|
|
pSVData->maWinData.mpFirstFrame = this;
|
|
mpWindowImpl->mpFrameData->mpFirstOverlap = nullptr;
|
|
mpWindowImpl->mpFrameData->mpFocusWin = nullptr;
|
|
mpWindowImpl->mpFrameData->mpMouseMoveWin = nullptr;
|
|
mpWindowImpl->mpFrameData->mpMouseDownWin = nullptr;
|
|
mpWindowImpl->mpFrameData->mpFontCollection = pSVData->maGDIData.mpScreenFontList;
|
|
mpWindowImpl->mpFrameData->mpFontCache = pSVData->maGDIData.mpScreenFontCache;
|
|
mpWindowImpl->mpFrameData->mnFocusId = nullptr;
|
|
mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
|
|
mpWindowImpl->mpFrameData->mnLastMouseX = -1;
|
|
mpWindowImpl->mpFrameData->mnLastMouseY = -1;
|
|
mpWindowImpl->mpFrameData->mnBeforeLastMouseX = -1;
|
|
mpWindowImpl->mpFrameData->mnBeforeLastMouseY = -1;
|
|
mpWindowImpl->mpFrameData->mnFirstMouseX = -1;
|
|
mpWindowImpl->mpFrameData->mnFirstMouseY = -1;
|
|
mpWindowImpl->mpFrameData->mnLastMouseWinX = -1;
|
|
mpWindowImpl->mpFrameData->mnLastMouseWinY = -1;
|
|
mpWindowImpl->mpFrameData->mnModalMode = 0;
|
|
mpWindowImpl->mpFrameData->mnMouseDownTime = 0;
|
|
mpWindowImpl->mpFrameData->mnClickCount = 0;
|
|
mpWindowImpl->mpFrameData->mnFirstMouseCode = 0;
|
|
mpWindowImpl->mpFrameData->mnMouseCode = 0;
|
|
mpWindowImpl->mpFrameData->mnMouseMode = MouseEventModifiers::NONE;
|
|
mpWindowImpl->mpFrameData->meMapUnit = MapUnit::MapPixel;
|
|
mpWindowImpl->mpFrameData->mbHasFocus = false;
|
|
mpWindowImpl->mpFrameData->mbInMouseMove = false;
|
|
mpWindowImpl->mpFrameData->mbMouseIn = false;
|
|
mpWindowImpl->mpFrameData->mbStartDragCalled = false;
|
|
mpWindowImpl->mpFrameData->mbNeedSysWindow = false;
|
|
mpWindowImpl->mpFrameData->mbMinimized = false;
|
|
mpWindowImpl->mpFrameData->mbStartFocusState = false;
|
|
mpWindowImpl->mpFrameData->mbInSysObjFocusHdl = false;
|
|
mpWindowImpl->mpFrameData->mbInSysObjToTopHdl = false;
|
|
mpWindowImpl->mpFrameData->mbSysObjFocus = false;
|
|
mpWindowImpl->mpFrameData->maPaintIdle.SetPriority( SchedulerPriority::REPAINT );
|
|
mpWindowImpl->mpFrameData->maPaintIdle.SetIdleHdl( LINK( this, Window, ImplHandlePaintHdl ) );
|
|
mpWindowImpl->mpFrameData->maPaintIdle.SetDebugName( "vcl::Window maPaintIdle" );
|
|
mpWindowImpl->mpFrameData->maResizeIdle.SetPriority( SchedulerPriority::RESIZE );
|
|
mpWindowImpl->mpFrameData->maResizeIdle.SetIdleHdl( LINK( this, Window, ImplHandleResizeTimerHdl ) );
|
|
mpWindowImpl->mpFrameData->maResizeIdle.SetDebugName( "vcl::Window maResizeIdle" );
|
|
mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = false;
|
|
if (!(nStyle & WB_DEFAULTWIN) && mpWindowImpl->mbDoubleBufferingRequested)
|
|
RequestDoubleBuffering(true);
|
|
mpWindowImpl->mpFrameData->mbInBufferedPaint = false;
|
|
|
|
if ( pRealParent && IsTopWindow() )
|
|
{
|
|
ImplWinData* pParentWinData = pRealParent->ImplGetWinData();
|
|
pParentWinData->maTopWindowChildren.push_back( this );
|
|
}
|
|
}
|
|
|
|
// init data
|
|
mpWindowImpl->mpRealParent = pRealParent;
|
|
|
|
// #99318: make sure fontcache and list is available before call to SetSettings
|
|
mpFontCollection = mpWindowImpl->mpFrameData->mpFontCollection;
|
|
mpFontCache = mpWindowImpl->mpFrameData->mpFontCache;
|
|
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
if ( pParent )
|
|
{
|
|
mpWindowImpl->mpFrameData->mnDPIX = pParent->mpWindowImpl->mpFrameData->mnDPIX;
|
|
mpWindowImpl->mpFrameData->mnDPIY = pParent->mpWindowImpl->mpFrameData->mnDPIY;
|
|
}
|
|
else
|
|
{
|
|
OutputDevice *pOutDev = GetOutDev();
|
|
if ( pOutDev->AcquireGraphics() )
|
|
{
|
|
mpGraphics->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().push_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.mpSettings );
|
|
OutputDevice::SetSettings( *pSVData->maAppData.mpSettings );
|
|
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( mnOutWidth, mnOutHeight );
|
|
}
|
|
else
|
|
{
|
|
if ( pParent )
|
|
{
|
|
if ( !ImplIsOverlapWindow() )
|
|
{
|
|
mpWindowImpl->mbDisabled = pParent->mpWindowImpl->mbDisabled;
|
|
mpWindowImpl->mbInputDisabled = pParent->mpWindowImpl->mbInputDisabled;
|
|
mpWindowImpl->meAlwaysInputMode = pParent->mpWindowImpl->meAlwaysInputMode;
|
|
}
|
|
|
|
if (!utl::ConfigManager::IsAvoidConfig())
|
|
OutputDevice::SetSettings( pParent->GetSettings() );
|
|
}
|
|
|
|
}
|
|
|
|
// setup the scale factor for Hi-DPI displays
|
|
mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
|
|
mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
|
|
mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
|
|
|
|
if (!utl::ConfigManager::IsAvoidConfig())
|
|
{
|
|
const StyleSettings& rStyleSettings = mxSettings->GetStyleSettings();
|
|
maFont = rStyleSettings.GetAppFont();
|
|
|
|
if ( nStyle & WB_3DLOOK )
|
|
{
|
|
SetTextColor( rStyleSettings.GetButtonTextColor() );
|
|
SetBackground( Wallpaper( rStyleSettings.GetFaceColor() ) );
|
|
}
|
|
else
|
|
{
|
|
SetTextColor( rStyleSettings.GetWindowTextColor() );
|
|
SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
maFont = GetDefaultFont( DefaultFontType::FIXED, LANGUAGE_ENGLISH_US, GetDefaultFontFlags::NONE );
|
|
}
|
|
|
|
ImplPointToLogic(*this, maFont);
|
|
|
|
(void)ImplUpdatePos();
|
|
|
|
// 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 );
|
|
|
|
if ( GetAccessibleParentWindow() && GetParent() != Application::GetDefDialogParent() )
|
|
GetAccessibleParentWindow()->CallEventListeners( VCLEVENT_WINDOW_CHILDCREATED, this );
|
|
}
|
|
|
|
void Window::ImplInitAppFontData( vcl::Window* pWindow )
|
|
{
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
long nTextHeight = pWindow->GetTextHeight();
|
|
long nTextWidth = pWindow->approximate_char_width() * 8;
|
|
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;
|
|
else if ( 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 OS X, 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;
|
|
Rectangle aCtrlRegion( Point(), Size( nTextWidth < 10 ? 10 : nTextWidth, nTextHeight < 10 ? 10 : nTextHeight ) );
|
|
Rectangle aBoundingRgn( aCtrlRegion );
|
|
Rectangle aContentRgn( aCtrlRegion );
|
|
if( pWindow->GetNativeControlRegion( ControlType::Editbox, ControlPart::Entire, aCtrlRegion,
|
|
ControlState::ENABLED, aControlValue, OUString(),
|
|
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
|
|
}
|
|
|
|
ImplWinData* Window::ImplGetWinData() const
|
|
{
|
|
if ( !mpWindowImpl->mpWinData )
|
|
{
|
|
static const char* pNoNWF = getenv( "SAL_NO_NWF" );
|
|
|
|
const_cast<vcl::Window*>(this)->mpWindowImpl->mpWinData = new ImplWinData;
|
|
mpWindowImpl->mpWinData->mbEnableNativeWidget = !(pNoNWF && *pNoNWF); // true: try to draw this control with native theme API
|
|
}
|
|
|
|
return mpWindowImpl->mpWinData;
|
|
}
|
|
|
|
|
|
void Window::CopyDeviceArea( SalTwoRect& aPosAry, bool bWindowInvalidate )
|
|
{
|
|
if (aPosAry.mnSrcWidth == 0 || aPosAry.mnSrcHeight == 0 || aPosAry.mnDestWidth == 0 || aPosAry.mnDestHeight == 0)
|
|
return;
|
|
|
|
if (bWindowInvalidate)
|
|
{
|
|
const Rectangle aSrcRect(Point(aPosAry.mnSrcX, aPosAry.mnSrcY),
|
|
Size(aPosAry.mnSrcWidth, aPosAry.mnSrcHeight));
|
|
|
|
ImplMoveAllInvalidateRegions(aSrcRect,
|
|
aPosAry.mnDestX-aPosAry.mnSrcX,
|
|
aPosAry.mnDestY-aPosAry.mnSrcY,
|
|
false);
|
|
|
|
mpGraphics->CopyArea(aPosAry.mnDestX, aPosAry.mnDestY,
|
|
aPosAry.mnSrcX, aPosAry.mnSrcY,
|
|
aPosAry.mnSrcWidth, aPosAry.mnSrcHeight,
|
|
this);
|
|
|
|
return;
|
|
}
|
|
|
|
OutputDevice::CopyDeviceArea(aPosAry, bWindowInvalidate);
|
|
}
|
|
|
|
SalGraphics* Window::ImplGetFrameGraphics() const
|
|
{
|
|
if ( mpWindowImpl->mpFrameWindow->mpGraphics )
|
|
{
|
|
mpWindowImpl->mpFrameWindow->mbInitClipRegion = true;
|
|
}
|
|
else
|
|
{
|
|
OutputDevice* pFrameWinOutDev = mpWindowImpl->mpFrameWindow;
|
|
if ( ! pFrameWinOutDev->AcquireGraphics() )
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
mpWindowImpl->mpFrameWindow->mpGraphics->ResetClipRegion();
|
|
return mpWindowImpl->mpFrameWindow->mpGraphics;
|
|
}
|
|
|
|
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();
|
|
|
|
bool bBecameReallyVisible = !mpWindowImpl->mbReallyVisible;
|
|
|
|
mbDevOutput = true;
|
|
mpWindowImpl->mbReallyVisible = true;
|
|
mpWindowImpl->mbReallyShown = true;
|
|
|
|
// 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( VCLEVENT_WINDOW_SHOW, this );
|
|
// TODO. It's kind of a hack that we're re-using the VCLEVENT_WINDOW_SHOW. 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)
|
|
{
|
|
mnDPIX = mpWindowImpl->mpFrameData->mnDPIX;
|
|
mnDPIY = mpWindowImpl->mpFrameData->mnDPIY;
|
|
|
|
// setup the scale factor for Hi-DPI displays
|
|
mnDPIScalePercentage = CountDPIScaleFactor(mpWindowImpl->mpFrameData->mnDPIY);
|
|
const StyleSettings& rStyleSettings = mxSettings->GetStyleSettings();
|
|
SetPointFont(*this, rStyleSettings.GetAppFont());
|
|
}
|
|
else if ( mpWindowImpl->mpParent )
|
|
{
|
|
mnDPIX = mpWindowImpl->mpParent->mnDPIX;
|
|
mnDPIY = mpWindowImpl->mpParent->mnDPIY;
|
|
mnDPIScalePercentage = mpWindowImpl->mpParent->mnDPIScalePercentage;
|
|
}
|
|
|
|
// update the recalculated values for logical units
|
|
// and also tools belonging to the values
|
|
if (IsMapModeEnabled())
|
|
{
|
|
MapMode aMapMode = GetMapMode();
|
|
SetMapMode();
|
|
SetMapMode( aMapMode );
|
|
}
|
|
}
|
|
|
|
void Window::ImplPointToLogic(vcl::RenderContext& rRenderContext, vcl::Font& rFont) const
|
|
{
|
|
Size aSize = rFont.GetFontSize();
|
|
|
|
if (aSize.Width())
|
|
{
|
|
aSize.Width() *= mpWindowImpl->mpFrameData->mnDPIX;
|
|
aSize.Width() += 72 / 2;
|
|
aSize.Width() /= 72;
|
|
}
|
|
aSize.Height() *= mpWindowImpl->mpFrameData->mnDPIY;
|
|
aSize.Height() += 72/2;
|
|
aSize.Height() /= 72;
|
|
|
|
if (rRenderContext.IsMapModeEnabled())
|
|
aSize = rRenderContext.PixelToLogic(aSize);
|
|
|
|
rFont.SetFontSize(aSize);
|
|
}
|
|
|
|
void Window::ImplLogicToPoint(vcl::RenderContext& rRenderContext, vcl::Font& rFont) const
|
|
{
|
|
Size aSize = rFont.GetFontSize();
|
|
|
|
if (rRenderContext.IsMapModeEnabled())
|
|
aSize = rRenderContext.LogicToPixel(aSize);
|
|
|
|
if (aSize.Width())
|
|
{
|
|
aSize.Width() *= 72;
|
|
aSize.Width() += mpWindowImpl->mpFrameData->mnDPIX / 2;
|
|
aSize.Width() /= mpWindowImpl->mpFrameData->mnDPIX;
|
|
}
|
|
aSize.Height() *= 72;
|
|
aSize.Height() += mpWindowImpl->mpFrameData->mnDPIY / 2;
|
|
aSize.Height() /= mpWindowImpl->mpFrameData->mnDPIY;
|
|
|
|
rFont.SetFontSize(aSize);
|
|
}
|
|
|
|
bool Window::ImplUpdatePos()
|
|
{
|
|
bool bSysChild = false;
|
|
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
mnOutOffX = mpWindowImpl->mnX;
|
|
mnOutOffY = mpWindowImpl->mnY;
|
|
}
|
|
else
|
|
{
|
|
vcl::Window* pParent = ImplGetParent();
|
|
|
|
mnOutOffX = mpWindowImpl->mnX + pParent->mnOutOffX;
|
|
mnOutOffY = mpWindowImpl->mnY + pParent->mnOutOffY;
|
|
}
|
|
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
if ( pChild->ImplUpdatePos() )
|
|
bSysChild = true;
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
if ( mpWindowImpl->mpSysObj )
|
|
bSysChild = true;
|
|
|
|
return bSysChild;
|
|
}
|
|
|
|
void Window::ImplUpdateSysObjPos()
|
|
{
|
|
if ( mpWindowImpl->mpSysObj )
|
|
mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
|
|
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->ImplUpdateSysObjPos();
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
void Window::ImplPosSizeWindow( long nX, long nY,
|
|
long nWidth, long nHeight, PosSizeFlags nFlags )
|
|
{
|
|
bool bNewPos = false;
|
|
bool bNewSize = false;
|
|
bool bCopyBits = false;
|
|
long nOldOutOffX = mnOutOffX;
|
|
long nOldOutOffY = mnOutOffY;
|
|
long nOldOutWidth = mnOutWidth;
|
|
long nOldOutHeight = mnOutHeight;
|
|
vcl::Region* pOverlapRegion = nullptr;
|
|
vcl::Region* pOldRegion = nullptr;
|
|
|
|
if ( IsReallyVisible() )
|
|
{
|
|
Rectangle aOldWinRect( Point( nOldOutOffX, nOldOutOffY ),
|
|
Size( nOldOutWidth, nOldOutHeight ) );
|
|
pOldRegion = new vcl::Region( aOldWinRect );
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
pOldRegion->Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
|
|
if ( mnOutWidth && mnOutHeight && !mpWindowImpl->mbPaintTransparent &&
|
|
!mpWindowImpl->mbInitWinClipRegion && !mpWindowImpl->maWinClipRegion.IsEmpty() &&
|
|
!HasPaintEvent() )
|
|
bCopyBits = true;
|
|
}
|
|
|
|
bool bnXRecycled = false; // avoid duplicate mirroring in RTL case
|
|
if ( nFlags & PosSizeFlags::Width )
|
|
{
|
|
if(!( nFlags & PosSizeFlags::X ))
|
|
{
|
|
nX = mpWindowImpl->mnX;
|
|
nFlags |= PosSizeFlags::X;
|
|
bnXRecycled = true; // we're using a mnX which was already mirrored in RTL case
|
|
}
|
|
|
|
if ( nWidth < 0 )
|
|
nWidth = 0;
|
|
if ( nWidth != mnOutWidth )
|
|
{
|
|
mnOutWidth = nWidth;
|
|
bNewSize = true;
|
|
bCopyBits = false;
|
|
}
|
|
}
|
|
if ( nFlags & PosSizeFlags::Height )
|
|
{
|
|
if ( nHeight < 0 )
|
|
nHeight = 0;
|
|
if ( nHeight != mnOutHeight )
|
|
{
|
|
mnOutHeight = nHeight;
|
|
bNewSize = true;
|
|
bCopyBits = false;
|
|
}
|
|
}
|
|
|
|
if ( nFlags & PosSizeFlags::X )
|
|
{
|
|
long nOrgX = nX;
|
|
// --- RTL --- (compare the screen coordinates)
|
|
Point aPtDev( Point( nX+mnOutOffX, 0 ) );
|
|
OutputDevice *pOutDev = GetOutDev();
|
|
if( pOutDev->HasMirroredGraphics() )
|
|
{
|
|
mpGraphics->mirror( aPtDev.X(), this );
|
|
|
|
// #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->ImplIsAntiparallel() )
|
|
{
|
|
// --- RTL --- (re-mirror at parent window)
|
|
nX = mpWindowImpl->mpParent->mnOutWidth - 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( ImplIsAntiparallel() )
|
|
{
|
|
aPtDev.X() = mpWindowImpl->mnAbsScreenX;
|
|
nOrgX = mpWindowImpl->maPos.X();
|
|
}
|
|
}
|
|
}
|
|
else if( !bnXRecycled && mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
|
|
{
|
|
// mirrored window in LTR UI
|
|
{
|
|
// --- RTL --- (re-mirror at parent window)
|
|
nX = mpWindowImpl->mpParent->mnOutWidth - 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 = new vcl::Region();
|
|
ImplCalcOverlapRegion( Rectangle( Point( mnOutOffX, mnOutOffY ),
|
|
Size( mnOutWidth, mnOutHeight ) ),
|
|
*pOverlapRegion, false, true );
|
|
}
|
|
mpWindowImpl->mnX = nX;
|
|
mpWindowImpl->maPos.X() = nOrgX;
|
|
mpWindowImpl->mnAbsScreenX = aPtDev.X(); // --- RTL --- (store real screen pos)
|
|
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 = new vcl::Region();
|
|
ImplCalcOverlapRegion( Rectangle( Point( mnOutOffX, mnOutOffY ),
|
|
Size( mnOutWidth, mnOutHeight ) ),
|
|
*pOverlapRegion, false, true );
|
|
}
|
|
mpWindowImpl->mnY = nY;
|
|
mpWindowImpl->maPos.Y() = nY;
|
|
bNewPos = true;
|
|
}
|
|
}
|
|
|
|
if ( bNewPos || bNewSize )
|
|
{
|
|
bool bUpdateSysObjPos = false;
|
|
if ( bNewPos )
|
|
bUpdateSysObjPos = ImplUpdatePos();
|
|
|
|
// 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,
|
|
mnOutWidth-mpWindowImpl->mpClientWindow->mpWindowImpl->mnLeftBorder-mpWindowImpl->mpClientWindow->mpWindowImpl->mnRightBorder,
|
|
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 );
|
|
}
|
|
|
|
// invalidate window content ?
|
|
if ( bNewPos || (mnOutWidth > nOldOutWidth) || (mnOutHeight > nOldOutHeight) )
|
|
{
|
|
if ( bNewPos )
|
|
{
|
|
bool bInvalidate = false;
|
|
bool bParentPaint = true;
|
|
if ( !ImplIsOverlapWindow() )
|
|
bParentPaint = mpWindowImpl->mpParent->IsPaintEnabled();
|
|
if ( bCopyBits && bParentPaint && !HasPaintEvent() )
|
|
{
|
|
Point aPoint( mnOutOffX, mnOutOffY );
|
|
vcl::Region aRegion( Rectangle( aPoint,
|
|
Size( mnOutWidth, mnOutHeight ) ) );
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
ImplClipBoundaries( aRegion, false, true );
|
|
if ( !pOverlapRegion->IsEmpty() )
|
|
{
|
|
pOverlapRegion->Move( mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY );
|
|
aRegion.Exclude( *pOverlapRegion );
|
|
}
|
|
if ( !aRegion.IsEmpty() )
|
|
{
|
|
// adapt Paint areas
|
|
ImplMoveAllInvalidateRegions( Rectangle( Point( nOldOutOffX, nOldOutOffY ),
|
|
Size( nOldOutWidth, nOldOutHeight ) ),
|
|
mnOutOffX-nOldOutOffX, mnOutOffY-nOldOutOffY,
|
|
true );
|
|
SalGraphics* pGraphics = ImplGetFrameGraphics();
|
|
if ( pGraphics )
|
|
{
|
|
|
|
OutputDevice *pOutDev = GetOutDev();
|
|
const bool bSelectClipRegion = pOutDev->SelectClipRegion( aRegion, pGraphics );
|
|
if ( bSelectClipRegion )
|
|
{
|
|
pGraphics->CopyArea( mnOutOffX, mnOutOffY,
|
|
nOldOutOffX, nOldOutOffY,
|
|
nOldOutWidth, nOldOutHeight,
|
|
this );
|
|
}
|
|
else
|
|
bInvalidate = true;
|
|
}
|
|
else
|
|
bInvalidate = true;
|
|
if ( !bInvalidate )
|
|
{
|
|
if ( !pOverlapRegion->IsEmpty() )
|
|
ImplInvalidateFrameRegion( pOverlapRegion, InvalidateFlags::Children );
|
|
}
|
|
}
|
|
else
|
|
bInvalidate = true;
|
|
}
|
|
else
|
|
bInvalidate = true;
|
|
if ( bInvalidate )
|
|
ImplInvalidateFrameRegion( nullptr, InvalidateFlags::Children );
|
|
}
|
|
else
|
|
{
|
|
Point aPoint( mnOutOffX, mnOutOffY );
|
|
vcl::Region aRegion( Rectangle( aPoint,
|
|
Size( mnOutWidth, mnOutHeight ) ) );
|
|
aRegion.Exclude( *pOldRegion );
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
ImplClipBoundaries( aRegion, false, true );
|
|
if ( !aRegion.IsEmpty() )
|
|
ImplInvalidateFrameRegion( &aRegion, InvalidateFlags::Children );
|
|
}
|
|
}
|
|
|
|
// invalidate Parent or Overlaps
|
|
if ( bNewPos ||
|
|
(mnOutWidth < nOldOutWidth) || (mnOutHeight < nOldOutHeight) )
|
|
{
|
|
vcl::Region aRegion( *pOldRegion );
|
|
if ( !mpWindowImpl->mbPaintTransparent )
|
|
ImplExcludeWindowRegion( aRegion );
|
|
ImplClipBoundaries( aRegion, false, true );
|
|
if ( !aRegion.IsEmpty() && !mpWindowImpl->mpBorderWindow )
|
|
ImplInvalidateParentFrameRegion( aRegion );
|
|
}
|
|
}
|
|
|
|
// adapt system objects
|
|
if ( bUpdateSysObjClip )
|
|
ImplUpdateSysObjClip();
|
|
if ( bUpdateSysObjPos )
|
|
ImplUpdateSysObjPos();
|
|
if ( bNewSize && mpWindowImpl->mpSysObj )
|
|
mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
|
|
}
|
|
|
|
delete pOverlapRegion;
|
|
delete pOldRegion;
|
|
}
|
|
|
|
void Window::ImplNewInputContext()
|
|
{
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
vcl::Window* pFocusWin = pSVData->maWinData.mpFocusWin;
|
|
if ( !pFocusWin )
|
|
return;
|
|
|
|
// Is InputContext changed?
|
|
const InputContext& rInputContext = pFocusWin->GetInputContext();
|
|
if ( rInputContext == pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext )
|
|
return;
|
|
|
|
pFocusWin->mpWindowImpl->mpFrameData->maOldInputContext = rInputContext;
|
|
|
|
SalInputContext aNewContext;
|
|
const vcl::Font& rFont = rInputContext.GetFont();
|
|
const OUString& rFontName = rFont.GetFamilyName();
|
|
LogicalFontInstance* pFontInstance = nullptr;
|
|
aNewContext.mpFont = nullptr;
|
|
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.Height() = 1;
|
|
else
|
|
aSize.Height() = (12*pFocusWin->mnDPIY)/72;
|
|
}
|
|
pFontInstance = pFocusWin->mpFontCache->GetFontInstance( pFocusWin->mpFontCollection,
|
|
rFont, aSize, static_cast<float>(aSize.Height()) );
|
|
if ( pFontInstance )
|
|
aNewContext.mpFont = &pFontInstance->maFontSelData;
|
|
}
|
|
aNewContext.meLanguage = rFont.GetLanguage();
|
|
aNewContext.mnOptions = rInputContext.GetOptions();
|
|
pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
|
|
|
|
if ( pFontInstance )
|
|
pFocusWin->mpFontCache->Release( pFontInstance );
|
|
}
|
|
|
|
void Window::doLazyDelete()
|
|
{
|
|
SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(this);
|
|
DockingWindow* pDockWin = dynamic_cast<DockingWindow*>(this);
|
|
if( pSysWin || ( pDockWin && pDockWin->IsFloatingMode() ) )
|
|
{
|
|
Show( false );
|
|
SetParent( ImplGetDefaultWindow() );
|
|
}
|
|
vcl::LazyDeletor::Delete( this );
|
|
}
|
|
|
|
KeyIndicatorState Window::GetIndicatorState() const
|
|
{
|
|
return mpWindowImpl->mpFrame->GetIndicatorState();
|
|
}
|
|
|
|
void Window::SimulateKeyPress( sal_uInt16 nKeyCode ) const
|
|
{
|
|
mpWindowImpl->mpFrame->SimulateKeyPress(nKeyCode);
|
|
}
|
|
|
|
void Window::KeyInput( const KeyEvent& rKEvt )
|
|
{
|
|
KeyCode cod = rKEvt.GetKeyCode ();
|
|
bool accel = ImplGetSVData()->maNWFData.mbEnableAccel;
|
|
bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel;
|
|
|
|
// do not respond to accelerators unless Alt is held */
|
|
if (cod.GetCode () >= 0x200 && cod.GetCode () <= 0x219)
|
|
{
|
|
if (!accel) return;
|
|
if (autoacc && cod.GetModifier () != KEY_MOD2) return;
|
|
}
|
|
|
|
NotifyEvent aNEvt( MouseNotifyEvent::KEYINPUT, this, &rKEvt );
|
|
if ( !CompatNotify( aNEvt ) )
|
|
mpWindowImpl->mbKeyInput = true;
|
|
}
|
|
|
|
void Window::KeyUp( const KeyEvent& rKEvt )
|
|
{
|
|
NotifyEvent aNEvt( MouseNotifyEvent::KEYUP, this, &rKEvt );
|
|
if ( !CompatNotify( aNEvt ) )
|
|
mpWindowImpl->mbKeyUp = true;
|
|
}
|
|
|
|
void Window::Draw( OutputDevice*, const Point&, const Size&, DrawFlags )
|
|
{
|
|
}
|
|
|
|
void Window::Move() {}
|
|
|
|
void Window::Resize() {}
|
|
|
|
void Window::Activate() {}
|
|
|
|
void Window::Deactivate() {}
|
|
|
|
void Window::GetFocus()
|
|
{
|
|
if ( HasFocus() && mpWindowImpl->mpLastFocusWindow && !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) )
|
|
{
|
|
VclPtr<vcl::Window> xWindow(this);
|
|
mpWindowImpl->mpLastFocusWindow->GrabFocus();
|
|
if( xWindow->IsDisposed() )
|
|
return;
|
|
}
|
|
|
|
NotifyEvent aNEvt( MouseNotifyEvent::GETFOCUS, this );
|
|
CompatNotify( aNEvt );
|
|
}
|
|
|
|
void Window::LoseFocus()
|
|
{
|
|
NotifyEvent aNEvt( MouseNotifyEvent::LOSEFOCUS, this );
|
|
CompatNotify( aNEvt );
|
|
}
|
|
|
|
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 = ImplGetParent()->OutputToScreenPixel( aPos );
|
|
Rectangle aRect( aPos, GetSizePixel() );
|
|
|
|
Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aRect, rStr );
|
|
}
|
|
}
|
|
else if ( rHEvt.GetMode() & HelpEventMode::QUICK )
|
|
{
|
|
const OUString& rStr = GetQuickHelpText();
|
|
if ( rStr.isEmpty() && ImplGetParent() && !ImplIsOverlapWindow() )
|
|
ImplGetParent()->RequestHelp( rHEvt );
|
|
else
|
|
{
|
|
Point aPos = GetPosPixel();
|
|
if ( ImplGetParent() && !ImplIsOverlapWindow() )
|
|
aPos = ImplGetParent()->OutputToScreenPixel( aPos );
|
|
Rectangle aRect( aPos, GetSizePixel() );
|
|
OUString aHelpText;
|
|
if ( !rStr.isEmpty() )
|
|
aHelpText = GetHelpText();
|
|
Help::ShowQuickHelp( this, aRect, rStr, aHelpText, QuickHelpFlags::CtrlText );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
|
|
if ( aStrHelpId.isEmpty() && ImplGetParent() )
|
|
ImplGetParent()->RequestHelp( rHEvt );
|
|
else
|
|
{
|
|
Help* pHelp = Application::GetHelp();
|
|
if ( pHelp )
|
|
{
|
|
if( !aStrHelpId.isEmpty() )
|
|
pHelp->Start( aStrHelpId, this );
|
|
else
|
|
pHelp->Start( OOO_HELP_INDEX, this );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Window::Command( const CommandEvent& rCEvt )
|
|
{
|
|
CallEventListeners( VCLEVENT_WINDOW_COMMAND, const_cast<CommandEvent *>(&rCEvt) );
|
|
|
|
NotifyEvent aNEvt( MouseNotifyEvent::COMMAND, this, &rCEvt );
|
|
if ( !CompatNotify( aNEvt ) )
|
|
mpWindowImpl->mbCommand = true;
|
|
}
|
|
|
|
void Window::Tracking( const TrackingEvent& rTEvt )
|
|
{
|
|
|
|
ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
|
|
if( pWrapper )
|
|
pWrapper->Tracking( rTEvt );
|
|
}
|
|
|
|
void Window::StateChanged(StateChangedType eType)
|
|
{
|
|
switch (eType)
|
|
{
|
|
//stuff that doesn't invalidate the layout
|
|
case StateChangedType::ControlForeground:
|
|
case StateChangedType::ControlBackground:
|
|
case StateChangedType::Transparent:
|
|
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;
|
|
}
|
|
}
|
|
|
|
bool Window::IsLocked() const
|
|
{
|
|
if ( mpWindowImpl->mnLockCount != 0 )
|
|
return true;
|
|
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
if ( pChild->IsLocked() )
|
|
return true;
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void Window::SetStyle( WinBits nStyle )
|
|
{
|
|
if ( mpWindowImpl && mpWindowImpl->mnStyle != nStyle )
|
|
{
|
|
mpWindowImpl->mnPrevStyle = mpWindowImpl->mnStyle;
|
|
mpWindowImpl->mnStyle = nStyle;
|
|
CompatStateChanged( StateChangedType::Style );
|
|
}
|
|
}
|
|
|
|
void Window::SetExtendedStyle( WinBits nExtendedStyle )
|
|
{
|
|
|
|
if ( mpWindowImpl->mnExtendedStyle != nExtendedStyle )
|
|
{
|
|
vcl::Window* pWindow = ImplGetBorderWindow();
|
|
if( ! pWindow )
|
|
pWindow = this;
|
|
if( pWindow->mpWindowImpl->mbFrame )
|
|
{
|
|
SalExtStyle nExt = 0;
|
|
if( (nExtendedStyle & WB_EXT_DOCUMENT) )
|
|
nExt |= SAL_FRAME_EXT_STYLE_DOCUMENT;
|
|
if( (nExtendedStyle & WB_EXT_DOCMODIFIED) )
|
|
nExt |= SAL_FRAME_EXT_STYLE_DOCMODIFIED;
|
|
|
|
pWindow->ImplGetFrame()->SetExtendedFrameStyle( nExt );
|
|
}
|
|
mpWindowImpl->mnPrevExtendedStyle = mpWindowImpl->mnExtendedStyle;
|
|
mpWindowImpl->mnExtendedStyle = nExtendedStyle;
|
|
CompatStateChanged( StateChangedType::ExtendedStyle );
|
|
}
|
|
}
|
|
|
|
void Window::SetBorderStyle( WindowBorderStyle nBorderStyle )
|
|
{
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
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() == WINDOW_BORDERWINDOW )
|
|
static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetBorderStyle( nBorderStyle );
|
|
else
|
|
mpWindowImpl->mpBorderWindow->SetBorderStyle( nBorderStyle );
|
|
}
|
|
}
|
|
}
|
|
|
|
WindowBorderStyle Window::GetBorderStyle() const
|
|
{
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
|
|
return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorderStyle();
|
|
else
|
|
return mpWindowImpl->mpBorderWindow->GetBorderStyle();
|
|
}
|
|
|
|
return WindowBorderStyle::NONE;
|
|
}
|
|
|
|
long Window::CalcTitleWidth() const
|
|
{
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
|
|
return static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->CalcTitleWidth();
|
|
else
|
|
return mpWindowImpl->mpBorderWindow->CalcTitleWidth();
|
|
}
|
|
else if ( mpWindowImpl->mbFrame && (mpWindowImpl->mnStyle & WB_MOVEABLE) )
|
|
{
|
|
// we guess the width for frame windows as we do not know the
|
|
// border of external dialogs
|
|
const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
|
|
vcl::Font aFont = GetFont();
|
|
const_cast<vcl::Window*>(this)->SetPointFont(*const_cast<Window*>(this), rStyleSettings.GetTitleFont());
|
|
long nTitleWidth = GetTextWidth( GetText() );
|
|
const_cast<vcl::Window*>(this)->SetFont( aFont );
|
|
nTitleWidth += rStyleSettings.GetTitleHeight() * 3;
|
|
nTitleWidth += rStyleSettings.GetBorderSize() * 2;
|
|
nTitleWidth += 10;
|
|
return nTitleWidth;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Window::SetInputContext( const InputContext& rInputContext )
|
|
{
|
|
|
|
mpWindowImpl->maInputContext = rInputContext;
|
|
if ( !mpWindowImpl->mbInFocusHdl && HasFocus() )
|
|
ImplNewInputContext();
|
|
}
|
|
|
|
void Window::EndExtTextInput()
|
|
{
|
|
|
|
if ( mpWindowImpl->mbExtTextInput )
|
|
ImplGetFrame()->EndExtTextInput( EndExtTextInputFlags::Complete );
|
|
}
|
|
|
|
void Window::SetCursorRect( const Rectangle* pRect, long nExtTextInputWidth )
|
|
{
|
|
|
|
ImplWinData* pWinData = ImplGetWinData();
|
|
if ( pWinData->mpCursorRect )
|
|
{
|
|
if ( pRect )
|
|
*pWinData->mpCursorRect = *pRect;
|
|
else
|
|
{
|
|
delete pWinData->mpCursorRect;
|
|
pWinData->mpCursorRect = nullptr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pRect )
|
|
pWinData->mpCursorRect = new Rectangle( *pRect );
|
|
}
|
|
|
|
pWinData->mnCursorExtWidth = nExtTextInputWidth;
|
|
|
|
}
|
|
|
|
const Rectangle* Window::GetCursorRect() const
|
|
{
|
|
|
|
ImplWinData* pWinData = ImplGetWinData();
|
|
return pWinData->mpCursorRect;
|
|
}
|
|
|
|
long Window::GetCursorExtTextInputWidth() const
|
|
{
|
|
|
|
ImplWinData* pWinData = ImplGetWinData();
|
|
return pWinData->mnCursorExtWidth;
|
|
}
|
|
|
|
void Window::SetCompositionCharRect( const Rectangle* pRect, long nCompositionLength, bool bVertical ) {
|
|
|
|
ImplWinData* pWinData = ImplGetWinData();
|
|
delete[] pWinData->mpCompositionCharRects;
|
|
pWinData->mbVertical = bVertical;
|
|
pWinData->mpCompositionCharRects = nullptr;
|
|
pWinData->mnCompositionCharRects = nCompositionLength;
|
|
if ( pRect && (nCompositionLength > 0) )
|
|
{
|
|
pWinData->mpCompositionCharRects = new Rectangle[nCompositionLength];
|
|
for (long i = 0; i < nCompositionLength; ++i)
|
|
pWinData->mpCompositionCharRects[i] = pRect[i];
|
|
}
|
|
}
|
|
|
|
void Window::CollectChildren(::std::vector<vcl::Window *>& rAllChildren )
|
|
{
|
|
rAllChildren.push_back( this );
|
|
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->CollectChildren( rAllChildren );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
void Window::SetPointFont(vcl::RenderContext& rRenderContext, const vcl::Font& rFont)
|
|
{
|
|
vcl::Font aFont = rFont;
|
|
ImplPointToLogic(rRenderContext, aFont);
|
|
rRenderContext.SetFont(aFont);
|
|
}
|
|
|
|
vcl::Font Window::GetPointFont(vcl::RenderContext& rRenderContext) const
|
|
{
|
|
vcl::Font aFont = rRenderContext.GetFont();
|
|
ImplLogicToPoint(rRenderContext, aFont);
|
|
return aFont;
|
|
}
|
|
|
|
void Window::Show(bool bVisible, ShowFlags nFlags)
|
|
{
|
|
if ( IsDisposed() || mpWindowImpl->mbVisible == bVisible )
|
|
return;
|
|
|
|
VclPtr<vcl::Window> xWindow(this);
|
|
|
|
bool bRealVisibilityChanged = false;
|
|
mpWindowImpl->mbVisible = bVisible;
|
|
|
|
if ( !bVisible )
|
|
{
|
|
ImplHideAllOverlaps();
|
|
if( xWindow->IsDisposed() )
|
|
return;
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
bool bOldUpdate = mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate;
|
|
if ( mpWindowImpl->mbNoParentUpdate )
|
|
mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = true;
|
|
mpWindowImpl->mpBorderWindow->Show( false, nFlags );
|
|
mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = bOldUpdate;
|
|
}
|
|
else if ( mpWindowImpl->mbFrame )
|
|
{
|
|
mpWindowImpl->mbSuppressAccessibilityEvents = true;
|
|
mpWindowImpl->mpFrame->Show( false );
|
|
}
|
|
|
|
CompatStateChanged( StateChangedType::Visible );
|
|
|
|
if ( mpWindowImpl->mbReallyVisible )
|
|
{
|
|
if ( mpWindowImpl->mbInitWinClipRegion )
|
|
ImplInitWinClipRegion();
|
|
|
|
vcl::Region aInvRegion = mpWindowImpl->maWinClipRegion;
|
|
|
|
if( xWindow->IsDisposed() )
|
|
return;
|
|
|
|
bRealVisibilityChanged = mpWindowImpl->mbReallyVisible;
|
|
ImplResetReallyVisible();
|
|
ImplSetClipFlag();
|
|
|
|
if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
|
|
{
|
|
// convert focus
|
|
if ( !(nFlags & ShowFlags::NoFocusChange) && HasChildPathFocus() )
|
|
{
|
|
if ( mpWindowImpl->mpOverlapWindow->IsEnabled() &&
|
|
mpWindowImpl->mpOverlapWindow->IsInputEnabled() &&
|
|
! mpWindowImpl->mpOverlapWindow->IsInModalMode()
|
|
)
|
|
mpWindowImpl->mpOverlapWindow->GrabFocus();
|
|
}
|
|
}
|
|
|
|
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
|
|
*/
|
|
const int workaround_border = 5;
|
|
Rectangle aBounds( aInvRegion.GetBoundRect() );
|
|
aBounds.Left() -= workaround_border;
|
|
aBounds.Top() -= workaround_border;
|
|
aBounds.Right() += workaround_border;
|
|
aBounds.Bottom() += workaround_border;
|
|
aInvRegion = aBounds;
|
|
}
|
|
if ( !mpWindowImpl->mbNoParentUpdate && !(nFlags & ShowFlags::NoParentUpdate) )
|
|
{
|
|
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()->IsCompoundControl() &&
|
|
GetParent()->IsNativeWidgetEnabled() != IsNativeWidgetEnabled() )
|
|
{
|
|
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() && !(nFlags & ShowFlags::NoActivate) )
|
|
{
|
|
ImplStartToTop(( nFlags & ShowFlags::ForegroundTask ) ? ToTopFlags::ForegroundTask : ToTopFlags::NONE );
|
|
ImplFocusToTop( ToTopFlags::NONE, false );
|
|
}
|
|
|
|
// adjust mpWindowImpl->mbReallyVisible
|
|
bRealVisibilityChanged = !mpWindowImpl->mbReallyVisible;
|
|
ImplSetReallyVisible();
|
|
|
|
// assure clip rectangles will be recalculated
|
|
ImplSetClipFlag();
|
|
|
|
if ( !mpWindowImpl->mbFrame )
|
|
{
|
|
InvalidateFlags nInvalidateFlags = InvalidateFlags::Children;
|
|
if( ! IsPaintTransparent() )
|
|
nInvalidateFlags |= InvalidateFlags::NoTransparent;
|
|
ImplInvalidate( nullptr, nInvalidateFlags );
|
|
ImplGenerateMouseMove();
|
|
}
|
|
}
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->Show( true, nFlags );
|
|
else if ( 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')
|
|
GetpApp()->InitFinished();
|
|
}
|
|
else if ( !ImplIsWindowOrChild( pSVData->mpIntroWindow ) )
|
|
{
|
|
// ... but the VCL splash is broken, and it needs this
|
|
// (for ./soffice .uno:NewDoc)
|
|
pSVData->mpIntroWindow->Hide();
|
|
}
|
|
|
|
//SAL_WARN_IF( mpWindowImpl->mbSuppressAccessibilityEvents, "vcl", "Window::Show() - Frame reactivated");
|
|
mpWindowImpl->mbSuppressAccessibilityEvents = false;
|
|
|
|
mpWindowImpl->mbPaintFrame = true;
|
|
if (!Application::GetSettings().GetMiscSettings().GetPseudoHeadless())
|
|
{
|
|
bool bNoActivate(nFlags & (ShowFlags::NoActivate|ShowFlags::NoFocusChange));
|
|
mpWindowImpl->mpFrame->Show( true, bNoActivate );
|
|
}
|
|
if( xWindow->IsDisposed() )
|
|
return;
|
|
|
|
// Query the correct size of the window, if we are waiting for
|
|
// a system resize
|
|
if ( mpWindowImpl->mbWaitSystemResize )
|
|
{
|
|
long nOutWidth;
|
|
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->IsDisposed() )
|
|
return;
|
|
|
|
ImplShowAllOverlaps();
|
|
}
|
|
|
|
if( xWindow->IsDisposed() )
|
|
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 ? VCLEVENT_WINDOW_SHOW : VCLEVENT_WINDOW_HIDE );
|
|
if( xWindow->IsDisposed() )
|
|
return;
|
|
|
|
}
|
|
|
|
Size Window::GetSizePixel() const
|
|
{
|
|
if (!mpWindowImpl)
|
|
{
|
|
SAL_WARN("vcl.layout", "WTF no windowimpl");
|
|
return Size(0,0);
|
|
}
|
|
|
|
// #i43257# trigger pending resize handler to assure correct window sizes
|
|
if( mpWindowImpl->mpFrameData->maResizeIdle.IsActive() )
|
|
{
|
|
VclPtr<vcl::Window> xWindow( const_cast<Window*>(this) );
|
|
mpWindowImpl->mpFrameData->maResizeIdle.Stop();
|
|
mpWindowImpl->mpFrameData->maResizeIdle.GetIdleHdl().Call( nullptr );
|
|
if( xWindow->IsDisposed() )
|
|
return Size(0,0);
|
|
}
|
|
|
|
return Size( mnOutWidth+mpWindowImpl->mnLeftBorder+mpWindowImpl->mnRightBorder,
|
|
mnOutHeight+mpWindowImpl->mnTopBorder+mpWindowImpl->mnBottomBorder );
|
|
}
|
|
|
|
void Window::GetBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder,
|
|
sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
|
|
{
|
|
rLeftBorder = mpWindowImpl->mnLeftBorder;
|
|
rTopBorder = mpWindowImpl->mnTopBorder;
|
|
rRightBorder = mpWindowImpl->mnRightBorder;
|
|
rBottomBorder = mpWindowImpl->mnBottomBorder;
|
|
}
|
|
|
|
void Window::Enable( bool bEnable, bool bChild )
|
|
{
|
|
if ( IsDisposed() )
|
|
return;
|
|
|
|
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 ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
mpWindowImpl->mpBorderWindow->Enable( bEnable, false );
|
|
if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
|
|
static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
|
|
static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->Enable( bEnable );
|
|
}
|
|
|
|
// #i56102# restore app focus win in case the
|
|
// window was disabled when the frame focus changed
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
if( bEnable &&
|
|
pSVData->maWinData.mpFocusWin == nullptr &&
|
|
mpWindowImpl->mpFrameData->mbHasFocus &&
|
|
mpWindowImpl->mpFrameData->mpFocusWin == this )
|
|
pSVData->maWinData.mpFocusWin = this;
|
|
|
|
if ( mpWindowImpl->mbDisabled != !bEnable )
|
|
{
|
|
mpWindowImpl->mbDisabled = !bEnable;
|
|
if ( mpWindowImpl->mpSysObj )
|
|
mpWindowImpl->mpSysObj->Enable( bEnable && !mpWindowImpl->mbInputDisabled );
|
|
CompatStateChanged( StateChangedType::Enable );
|
|
|
|
CallEventListeners( bEnable ? VCLEVENT_WINDOW_ENABLED : VCLEVENT_WINDOW_DISABLED );
|
|
}
|
|
|
|
if ( bChild )
|
|
{
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->Enable( bEnable, bChild );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
if ( IsReallyVisible() )
|
|
ImplGenerateMouseMove();
|
|
}
|
|
|
|
void Window::SetCallHandlersOnInputDisabled( bool bCall )
|
|
{
|
|
mpWindowImpl->mbCallHandlersDuringInputDisabled = bCall;
|
|
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->SetCallHandlersOnInputDisabled( bCall );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
bool Window::IsCallHandlersOnInputDisabled() const
|
|
{
|
|
return mpWindowImpl->mbCallHandlersDuringInputDisabled;
|
|
}
|
|
|
|
void Window::EnableInput( bool bEnable, bool bChild )
|
|
{
|
|
|
|
bool bNotify = (bEnable != mpWindowImpl->mbInputDisabled);
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
mpWindowImpl->mpBorderWindow->EnableInput( bEnable, false );
|
|
if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
|
|
static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow )
|
|
static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->mpMenuBarWindow->EnableInput( bEnable );
|
|
}
|
|
|
|
if ( (! bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled) ||
|
|
( bEnable && mpWindowImpl->meAlwaysInputMode != AlwaysInputDisabled) )
|
|
{
|
|
// automatically stop the tracking mode or steal capture
|
|
// if the window is disabled
|
|
if ( !bEnable )
|
|
{
|
|
if ( IsTracking() )
|
|
EndTracking( TrackingEventFlags::Cancel );
|
|
if ( IsMouseCaptured() )
|
|
ReleaseMouse();
|
|
}
|
|
|
|
if ( mpWindowImpl->mbInputDisabled != !bEnable )
|
|
{
|
|
mpWindowImpl->mbInputDisabled = !bEnable;
|
|
if ( mpWindowImpl->mpSysObj )
|
|
mpWindowImpl->mpSysObj->Enable( !mpWindowImpl->mbDisabled && bEnable );
|
|
}
|
|
}
|
|
|
|
// #i56102# restore app focus win in case the
|
|
// window was disabled when the frame focus changed
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
if( bEnable &&
|
|
pSVData->maWinData.mpFocusWin == nullptr &&
|
|
mpWindowImpl->mpFrameData->mbHasFocus &&
|
|
mpWindowImpl->mpFrameData->mpFocusWin == this )
|
|
pSVData->maWinData.mpFocusWin = this;
|
|
|
|
if ( bChild )
|
|
{
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->EnableInput( bEnable, bChild );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
if ( IsReallyVisible() )
|
|
ImplGenerateMouseMove();
|
|
|
|
// #104827# notify parent
|
|
if ( bNotify )
|
|
{
|
|
NotifyEvent aNEvt( bEnable ? MouseNotifyEvent::INPUTENABLE : MouseNotifyEvent::INPUTDISABLE, this );
|
|
CompatNotify( aNEvt );
|
|
}
|
|
}
|
|
|
|
void Window::EnableInput( bool bEnable, const vcl::Window* pExcludeWindow )
|
|
{
|
|
EnableInput( bEnable );
|
|
|
|
// pExecuteWindow is the first Overlap-Frame --> if this
|
|
// shouldn't be the case, than 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, than 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()->maWinData.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, than 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 )
|
|
{
|
|
::std::vector< VclPtr<vcl::Window> >& rList = mpWindowImpl->mpFrameData->maOwnerDrawList;
|
|
auto p = rList.begin();
|
|
while( p != rList.end() )
|
|
{
|
|
// Is Window in the path from this window
|
|
if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( (*p), true ) )
|
|
{
|
|
// Is Window not in the exclude window path or not the
|
|
// exclude window, than change the status
|
|
if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( (*p), true ) )
|
|
(*p)->EnableInput( bEnable );
|
|
}
|
|
++p;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Window::AlwaysEnableInput( bool bAlways, bool bChild )
|
|
{
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->AlwaysEnableInput( bAlways, false );
|
|
|
|
if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled )
|
|
{
|
|
mpWindowImpl->meAlwaysInputMode = AlwaysInputEnabled;
|
|
|
|
if ( bAlways )
|
|
EnableInput( true, false );
|
|
}
|
|
else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled )
|
|
{
|
|
mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
|
|
}
|
|
|
|
if ( bChild )
|
|
{
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->AlwaysEnableInput( bAlways, bChild );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Window::AlwaysDisableInput( bool bAlways, bool bChild )
|
|
{
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->AlwaysDisableInput( bAlways, false );
|
|
|
|
if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputDisabled )
|
|
{
|
|
mpWindowImpl->meAlwaysInputMode = AlwaysInputDisabled;
|
|
|
|
if ( bAlways )
|
|
EnableInput( false, false );
|
|
}
|
|
else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputDisabled )
|
|
{
|
|
mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
|
|
}
|
|
|
|
if ( bChild )
|
|
{
|
|
vcl::Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->AlwaysDisableInput( bAlways, bChild );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Window::SetActivateMode( ActivateModeFlags nMode )
|
|
{
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->SetActivateMode( nMode );
|
|
|
|
if ( mpWindowImpl->mnActivateMode != nMode )
|
|
{
|
|
mpWindowImpl->mnActivateMode = nMode;
|
|
|
|
// possibly trigger Decativate/Activate
|
|
if ( mpWindowImpl->mnActivateMode != ActivateModeFlags::NONE )
|
|
{
|
|
if ( (mpWindowImpl->mbActive || (GetType() == WINDOW_BORDERWINDOW)) &&
|
|
!HasChildPathFocus( true ) )
|
|
{
|
|
mpWindowImpl->mbActive = false;
|
|
Deactivate();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !mpWindowImpl->mbActive || (GetType() == WINDOW_BORDERWINDOW) )
|
|
{
|
|
mpWindowImpl->mbActive = true;
|
|
Activate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Window::setPosSizePixel( long nX, long nY,
|
|
long nWidth, long nHeight, PosSizeFlags nFlags )
|
|
{
|
|
bool bHasValidSize = !mpWindowImpl->mbDefSize;
|
|
|
|
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
|
|
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)
|
|
long nOldWidth = pWindow->mnOutWidth;
|
|
|
|
if ( !(nFlags & PosSizeFlags::Width) )
|
|
nWidth = pWindow->mnOutWidth;
|
|
if ( !(nFlags & PosSizeFlags::Height) )
|
|
nHeight = pWindow->mnOutHeight;
|
|
|
|
sal_uInt16 nSysFlags=0;
|
|
vcl::Window *pParent = GetParent();
|
|
|
|
if( nFlags & PosSizeFlags::Width )
|
|
nSysFlags |= SAL_FRAME_POSSIZE_WIDTH;
|
|
if( nFlags & PosSizeFlags::Height )
|
|
nSysFlags |= SAL_FRAME_POSSIZE_HEIGHT;
|
|
if( nFlags & PosSizeFlags::X )
|
|
{
|
|
nSysFlags |= SAL_FRAME_POSSIZE_X;
|
|
if( pParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
|
|
{
|
|
nX += pParent->mnOutOffX;
|
|
}
|
|
if( pParent && pParent->ImplIsAntiparallel() )
|
|
{
|
|
// --- RTL --- (re-mirror at parent window)
|
|
Rectangle aRect( Point ( nX, nY ), Size( nWidth, nHeight ) );
|
|
const OutputDevice *pParentOutDev = pParent->GetOutDev();
|
|
pParentOutDev->ReMirror( aRect );
|
|
nX = aRect.Left();
|
|
}
|
|
}
|
|
if( !(nFlags & PosSizeFlags::X) && bHasValidSize && pWindow->mpWindowImpl->mpFrame->maGeometry.nWidth )
|
|
{
|
|
// --- RTL --- make sure the old right aligned position is not changed
|
|
// system windows will always grow to the right
|
|
if ( pParent )
|
|
{
|
|
OutputDevice *pParentOutDev = pParent->GetOutDev();
|
|
if( pParentOutDev->HasMirroredGraphics() )
|
|
{
|
|
long myWidth = nOldWidth;
|
|
if( !myWidth )
|
|
myWidth = mpWindowImpl->mpFrame->GetUnmirroredGeometry().nWidth;
|
|
if( !myWidth )
|
|
myWidth = nWidth;
|
|
nFlags |= PosSizeFlags::X;
|
|
nSysFlags |= SAL_FRAME_POSSIZE_X;
|
|
nX = pParent->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX - mpWindowImpl->mpFrame->GetUnmirroredGeometry().nLeftDecoration +
|
|
pParent->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nWidth - myWidth - 1 - mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX;
|
|
if(!(nFlags & PosSizeFlags::Y))
|
|
{
|
|
nFlags |= PosSizeFlags::Y;
|
|
nSysFlags |= SAL_FRAME_POSSIZE_Y;
|
|
nY = mpWindowImpl->mpFrame->GetUnmirroredGeometry().nY - pWindow->GetParent()->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nY -
|
|
mpWindowImpl->mpFrame->GetUnmirroredGeometry().nTopDecoration;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if( nFlags & PosSizeFlags::Y )
|
|
{
|
|
nSysFlags |= SAL_FRAME_POSSIZE_Y;
|
|
if( pParent && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
|
|
{
|
|
nY += pParent->mnOutOffY;
|
|
}
|
|
}
|
|
|
|
if( nSysFlags & (SAL_FRAME_POSSIZE_WIDTH|SAL_FRAME_POSSIZE_HEIGHT) )
|
|
{
|
|
// check for min/max client size and adjust size accordingly
|
|
// otherwise it may happen that the resize event is ignored, i.e. the old size remains
|
|
// unchanged but ImplHandleResize() is called with the wrong size
|
|
SystemWindow *pSystemWindow = dynamic_cast< SystemWindow* >( pWindow );
|
|
if( pSystemWindow )
|
|
{
|
|
Size aMinSize = pSystemWindow->GetMinOutputSizePixel();
|
|
Size aMaxSize = pSystemWindow->GetMaxOutputSizePixel();
|
|
if( nWidth < aMinSize.Width() )
|
|
nWidth = aMinSize.Width();
|
|
if( nHeight < aMinSize.Height() )
|
|
nHeight = aMinSize.Height();
|
|
|
|
if( nWidth > aMaxSize.Width() )
|
|
nWidth = aMaxSize.Width();
|
|
if( nHeight > aMaxSize.Height() )
|
|
nHeight = aMaxSize.Height();
|
|
}
|
|
}
|
|
|
|
pWindow->mpWindowImpl->mpFrame->SetPosSize( nX, nY, nWidth, nHeight, nSysFlags );
|
|
|
|
// 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 to small or to large.
|
|
ImplHandleResize( pWindow, nWidth, nHeight );
|
|
}
|
|
else
|
|
{
|
|
pWindow->ImplPosSizeWindow( nX, nY, nWidth, nHeight, nFlags );
|
|
if ( IsReallyVisible() )
|
|
ImplGenerateMouseMove();
|
|
}
|
|
}
|
|
|
|
Point Window::GetPosPixel() const
|
|
{
|
|
return mpWindowImpl->maPos;
|
|
}
|
|
|
|
Rectangle Window::GetDesktopRectPixel() const
|
|
{
|
|
Rectangle rRect;
|
|
mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrame->GetWorkArea( rRect );
|
|
return rRect;
|
|
}
|
|
|
|
Point Window::OutputToScreenPixel( const Point& rPos ) const
|
|
{
|
|
// relative to top level parent
|
|
return Point( rPos.X()+mnOutOffX, rPos.Y()+mnOutOffY );
|
|
}
|
|
|
|
Point Window::ScreenToOutputPixel( const Point& rPos ) const
|
|
{
|
|
// relative to top level parent
|
|
return Point( rPos.X()-mnOutOffX, rPos.Y()-mnOutOffY );
|
|
}
|
|
|
|
long Window::ImplGetUnmirroredOutOffX()
|
|
{
|
|
// revert mnOutOffX changes that were potentially made in ImplPosSizeWindow
|
|
long offx = mnOutOffX;
|
|
OutputDevice *pOutDev = GetOutDev();
|
|
if( pOutDev->HasMirroredGraphics() )
|
|
{
|
|
if( mpWindowImpl->mpParent && !mpWindowImpl->mpParent->mpWindowImpl->mbFrame && mpWindowImpl->mpParent->ImplIsAntiparallel() )
|
|
{
|
|
if ( !ImplIsOverlapWindow() )
|
|
offx -= mpWindowImpl->mpParent->mnOutOffX;
|
|
|
|
offx = mpWindowImpl->mpParent->mnOutWidth - mnOutWidth - offx;
|
|
|
|
if ( !ImplIsOverlapWindow() )
|
|
offx += mpWindowImpl->mpParent->mnOutOffX;
|
|
|
|
}
|
|
}
|
|
return offx;
|
|
}
|
|
|
|
// normalized screen pixel are independent of mirroring
|
|
Point Window::OutputToNormalizedScreenPixel( const Point& rPos ) const
|
|
{
|
|
// relative to top level parent
|
|
long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX();
|
|
return Point( rPos.X()+offx, rPos.Y()+mnOutOffY );
|
|
}
|
|
|
|
Point Window::NormalizedScreenToOutputPixel( const Point& rPos ) const
|
|
{
|
|
// relative to top level parent
|
|
long offx = const_cast<vcl::Window*>(this)->ImplGetUnmirroredOutOffX();
|
|
return Point( rPos.X()-offx, rPos.Y()-mnOutOffY );
|
|
}
|
|
|
|
Point Window::OutputToAbsoluteScreenPixel( const Point& rPos ) const
|
|
{
|
|
// relative to the screen
|
|
Point p = OutputToScreenPixel( rPos );
|
|
SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
|
|
p.X() += g.nX;
|
|
p.Y() += g.nY;
|
|
return p;
|
|
}
|
|
|
|
Point Window::AbsoluteScreenToOutputPixel( const Point& rPos ) const
|
|
{
|
|
// relative to the screen
|
|
Point p = ScreenToOutputPixel( rPos );
|
|
SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
|
|
p.X() -= g.nX;
|
|
p.Y() -= g.nY;
|
|
return p;
|
|
}
|
|
|
|
Rectangle Window::ImplOutputToUnmirroredAbsoluteScreenPixel( const 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();
|
|
|
|
Point p1 = OutputToScreenPixel( rRect.TopRight() );
|
|
p1.X() = g.nX+g.nWidth-p1.X();
|
|
p1.Y() += g.nY;
|
|
|
|
Point p2 = OutputToScreenPixel( rRect.BottomLeft() );
|
|
p2.X() = g.nX+g.nWidth-p2.X();
|
|
p2.Y() += g.nY;
|
|
|
|
return Rectangle( p1, p2 );
|
|
}
|
|
|
|
Rectangle Window::GetWindowExtentsRelative( vcl::Window *pRelativeWindow ) const
|
|
{
|
|
// with decoration
|
|
return ImplGetWindowExtentsRelative( pRelativeWindow, false );
|
|
}
|
|
|
|
Rectangle Window::GetClientWindowExtentsRelative() const
|
|
{
|
|
// without decoration
|
|
return ImplGetWindowExtentsRelative( nullptr, true );
|
|
}
|
|
|
|
Rectangle Window::ImplGetWindowExtentsRelative( vcl::Window *pRelativeWindow, bool bClientOnly ) const
|
|
{
|
|
SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
|
|
// make sure we use the extent of our border window,
|
|
// otherwise we miss a few pixels
|
|
const vcl::Window *pWin = (!bClientOnly && mpWindowImpl->mpBorderWindow) ? mpWindowImpl->mpBorderWindow : this;
|
|
|
|
Point aPos( pWin->OutputToScreenPixel( Point(0,0) ) );
|
|
aPos.X() += g.nX;
|
|
aPos.Y() += g.nY;
|
|
Size aSize ( pWin->GetSizePixel() );
|
|
// #104088# do not add decoration to the workwindow to be compatible to java accessibility api
|
|
if( !bClientOnly && (mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && GetType() != WINDOW_WORKWINDOW)) )
|
|
{
|
|
aPos.X() -= g.nLeftDecoration;
|
|
aPos.Y() -= g.nTopDecoration;
|
|
aSize.Width() += g.nLeftDecoration + g.nRightDecoration;
|
|
aSize.Height() += g.nTopDecoration + g.nBottomDecoration;
|
|
}
|
|
if( pRelativeWindow )
|
|
{
|
|
// #106399# express coordinates relative to borderwindow
|
|
vcl::Window *pRelWin = (!bClientOnly && pRelativeWindow->mpWindowImpl->mpBorderWindow) ? pRelativeWindow->mpWindowImpl->mpBorderWindow.get() : pRelativeWindow;
|
|
aPos = pRelWin->AbsoluteScreenToOutputPixel( aPos );
|
|
}
|
|
return Rectangle( aPos, aSize );
|
|
}
|
|
|
|
void Window::Scroll( long nHorzScroll, long nVertScroll, ScrollFlags nFlags )
|
|
{
|
|
|
|
ImplScroll( Rectangle( Point( mnOutOffX, mnOutOffY ),
|
|
Size( mnOutWidth, mnOutHeight ) ),
|
|
nHorzScroll, nVertScroll, nFlags & ~ScrollFlags::Clip );
|
|
}
|
|
|
|
void Window::Scroll( long nHorzScroll, long nVertScroll,
|
|
const Rectangle& rRect, ScrollFlags nFlags )
|
|
{
|
|
OutputDevice *pOutDev = GetOutDev();
|
|
Rectangle aRect = pOutDev->ImplLogicToDevicePixel( rRect );
|
|
aRect.Intersection( Rectangle( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ) );
|
|
if ( !aRect.IsEmpty() )
|
|
ImplScroll( aRect, nHorzScroll, nVertScroll, nFlags );
|
|
}
|
|
|
|
void Window::Flush()
|
|
{
|
|
|
|
const Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
mpWindowImpl->mpFrame->Flush( aWinRect );
|
|
}
|
|
|
|
void Window::SetUpdateMode( bool bUpdate )
|
|
{
|
|
mpWindowImpl->mbNoUpdate = !bUpdate;
|
|
CompatStateChanged( StateChangedType::UpdateMode );
|
|
}
|
|
|
|
void Window::GrabFocus()
|
|
{
|
|
ImplGrabFocus( GetFocusFlags::NONE );
|
|
}
|
|
|
|
bool Window::HasFocus() const
|
|
{
|
|
return (this == ImplGetSVData()->maWinData.mpFocusWin);
|
|
}
|
|
|
|
void Window::GrabFocusToDocument()
|
|
{
|
|
ImplGrabFocusToDocument(GetFocusFlags::NONE);
|
|
}
|
|
|
|
void Window::SetFakeFocus( bool bFocus )
|
|
{
|
|
ImplGetWindowImpl()->mbFakeFocusSet = bFocus;
|
|
}
|
|
|
|
bool Window::HasChildPathFocus( bool bSystemWindow ) const
|
|
{
|
|
|
|
vcl::Window* pFocusWin = ImplGetSVData()->maWinData.mpFocusWin;
|
|
if ( pFocusWin )
|
|
return ImplIsWindowOrChild( pFocusWin, bSystemWindow );
|
|
return false;
|
|
}
|
|
|
|
void Window::SetCursor( vcl::Cursor* pCursor )
|
|
{
|
|
|
|
if ( mpWindowImpl->mpCursor != pCursor )
|
|
{
|
|
if ( mpWindowImpl->mpCursor )
|
|
mpWindowImpl->mpCursor->ImplHide();
|
|
mpWindowImpl->mpCursor = pCursor;
|
|
if ( pCursor )
|
|
pCursor->ImplShow();
|
|
}
|
|
}
|
|
|
|
void Window::SetText( const OUString& rStr )
|
|
{
|
|
if (!mpWindowImpl || rStr == mpWindowImpl->maText)
|
|
return;
|
|
|
|
OUString oldTitle( mpWindowImpl->maText );
|
|
mpWindowImpl->maText = rStr;
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->SetText( rStr );
|
|
else if ( mpWindowImpl->mbFrame )
|
|
mpWindowImpl->mpFrame->SetTitle( rStr );
|
|
|
|
CallEventListeners( VCLEVENT_WINDOW_FRAMETITLECHANGED, &oldTitle );
|
|
|
|
// #107247# needed for accessibility
|
|
// The VCLEVENT_WINDOW_FRAMETITLECHANGED 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( VCLEVENT_WINDOW_FRAMETITLECHANGED, &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 )
|
|
{
|
|
if( IsNativeWidgetEnabled() )
|
|
return pTB->ImplGetToolBoxPrivateData()->maDisplayBackground;
|
|
}
|
|
|
|
if( !IsBackground() )
|
|
{
|
|
if( mpWindowImpl->mpParent )
|
|
return mpWindowImpl->mpParent->GetDisplayBackground();
|
|
}
|
|
|
|
const Wallpaper& rBack = GetBackground();
|
|
if( ! rBack.IsBitmap() &&
|
|
! rBack.IsGradient() &&
|
|
rBack.GetColor().GetColor() == COL_TRANSPARENT &&
|
|
mpWindowImpl->mpParent )
|
|
return mpWindowImpl->mpParent->GetDisplayBackground();
|
|
return rBack;
|
|
}
|
|
|
|
const OUString& Window::GetHelpText() const
|
|
{
|
|
OUString aStrHelpId( OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
|
|
bool bStrHelpId = !aStrHelpId.isEmpty();
|
|
|
|
if ( !mpWindowImpl->maHelpText.getLength() && bStrHelpId )
|
|
{
|
|
if ( !IsDialog() && (mpWindowImpl->mnType != WINDOW_TABPAGE) && (mpWindowImpl->mnType != WINDOW_FLOATINGWINDOW) )
|
|
{
|
|
Help* pHelp = Application::GetHelp();
|
|
if ( pHelp )
|
|
{
|
|
mpWindowImpl->maHelpText = pHelp->GetHelpText(aStrHelpId, this);
|
|
mpWindowImpl->mbHelpTextDynamic = false;
|
|
}
|
|
}
|
|
}
|
|
else if( mpWindowImpl->mbHelpTextDynamic && bStrHelpId )
|
|
{
|
|
static const char* pEnv = getenv( "HELP_DEBUG" );
|
|
if( pEnv && *pEnv )
|
|
{
|
|
OUStringBuffer aTxt( 64+mpWindowImpl->maHelpText.getLength() );
|
|
aTxt.append( mpWindowImpl->maHelpText );
|
|
aTxt.append( "\n------------------\n" );
|
|
aTxt.append( OUString( aStrHelpId ) );
|
|
mpWindowImpl->maHelpText = aTxt.makeStringAndClear();
|
|
}
|
|
mpWindowImpl->mbHelpTextDynamic = false;
|
|
}
|
|
|
|
return mpWindowImpl->maHelpText;
|
|
}
|
|
|
|
void Window::SetWindowPeer( Reference< css::awt::XWindowPeer > const & xPeer, VCLXWindow* pVCLXWindow )
|
|
{
|
|
assert(mpWindowImpl);
|
|
|
|
// be safe against re-entrance: first clear the old ref, then assign the new one
|
|
mpWindowImpl->mxWindowPeer.clear();
|
|
mpWindowImpl->mxWindowPeer = xPeer;
|
|
|
|
mpWindowImpl->mpVCLXWindow = pVCLXWindow;
|
|
}
|
|
|
|
Reference< css::awt::XWindowPeer > Window::GetComponentInterface( bool bCreate )
|
|
{
|
|
if ( !mpWindowImpl->mxWindowPeer.is() && bCreate )
|
|
{
|
|
UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
|
|
if ( pWrapper )
|
|
mpWindowImpl->mxWindowPeer = pWrapper->GetWindowInterface( this );
|
|
}
|
|
return mpWindowImpl->mxWindowPeer;
|
|
}
|
|
|
|
void Window::SetComponentInterface( Reference< css::awt::XWindowPeer > const & xIFace )
|
|
{
|
|
UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
|
|
SAL_WARN_IF( !pWrapper, "vcl", "SetComponentInterface: No Wrapper!" );
|
|
if ( pWrapper )
|
|
pWrapper->SetWindowInterface( this, xIFace );
|
|
}
|
|
|
|
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( VCLEVENT_WINDOW_DEACTIVATE );
|
|
if( xWindow->IsDisposed() )
|
|
return;
|
|
|
|
// #100759#, avoid walking the wrong frame's hierarchy
|
|
// eg, undocked docking windows (ImplDockFloatWin)
|
|
if ( ImplGetParent() && 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 ) )
|
|
{
|
|
VclPtr<vcl::Window> xWindow(this);
|
|
CallEventListeners( VCLEVENT_WINDOW_ACTIVATE, pOld );
|
|
if( xWindow->IsDisposed() )
|
|
return;
|
|
|
|
if ( ImplGetParent() )
|
|
ImplGetParent()->ImplCallActivateListeners( pOld );
|
|
else if( (mpWindowImpl->mnStyle & WB_INTROWIN) == 0 )
|
|
{
|
|
// top level frame reached: store hint for DefModalDialogParent
|
|
ImplGetSVData()->maWinData.mpActiveApplicationFrame = mpWindowImpl->mpFrameWindow;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Window::SetClipboard(Reference<XClipboard> const & xClipboard)
|
|
{
|
|
if (mpWindowImpl->mpFrameData)
|
|
mpWindowImpl->mpFrameData->mxClipboard = xClipboard;
|
|
}
|
|
|
|
Reference< XClipboard > Window::GetClipboard()
|
|
{
|
|
|
|
if( mpWindowImpl->mpFrameData )
|
|
{
|
|
if( ! mpWindowImpl->mpFrameData->mxClipboard.is() )
|
|
{
|
|
try
|
|
{
|
|
mpWindowImpl->mpFrameData->mxClipboard
|
|
= css::datatransfer::clipboard::SystemClipboard::create(
|
|
comphelper::getProcessComponentContext());
|
|
}
|
|
catch (DeploymentException & e)
|
|
{
|
|
SAL_WARN(
|
|
"vcl.window",
|
|
"ignoring DeploymentException \"" << e.Message << "\"");
|
|
}
|
|
}
|
|
|
|
return mpWindowImpl->mpFrameData->mxClipboard;
|
|
}
|
|
|
|
return static_cast < XClipboard * > (nullptr);
|
|
}
|
|
|
|
Reference< XClipboard > Window::GetPrimarySelection()
|
|
{
|
|
|
|
if( mpWindowImpl->mpFrameData )
|
|
{
|
|
if( ! mpWindowImpl->mpFrameData->mxSelection.is() )
|
|
{
|
|
try
|
|
{
|
|
Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
|
|
|
|
#if HAVE_FEATURE_X11
|
|
// A hack, making the primary selection available as an instance
|
|
// of the SystemClipboard service on X11:
|
|
Sequence< Any > args(1);
|
|
args[0] <<= OUString("PRIMARY");
|
|
mpWindowImpl->mpFrameData->mxSelection.set(
|
|
(xContext->getServiceManager()->
|
|
createInstanceWithArgumentsAndContext(
|
|
"com.sun.star.datatransfer.clipboard.SystemClipboard",
|
|
args, xContext)),
|
|
UNO_QUERY_THROW);
|
|
#else
|
|
static Reference< XClipboard > s_xSelection(
|
|
xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.datatransfer.clipboard.GenericClipboard", xContext ), UNO_QUERY );
|
|
|
|
mpWindowImpl->mpFrameData->mxSelection = s_xSelection;
|
|
#endif
|
|
}
|
|
catch (RuntimeException & e)
|
|
{
|
|
SAL_WARN(
|
|
"vcl.window",
|
|
"ignoring RuntimeException \"" << e.Message << "\"");
|
|
}
|
|
}
|
|
|
|
return mpWindowImpl->mpFrameData->mxSelection;
|
|
}
|
|
|
|
return static_cast < XClipboard * > (nullptr);
|
|
}
|
|
|
|
void Window::RecordLayoutData( vcl::ControlLayoutData* pLayout, const Rectangle& rRect )
|
|
{
|
|
assert(mpOutDevData);
|
|
mpOutDevData->mpRecordLayout = pLayout;
|
|
mpOutDevData->maRecordRect = rRect;
|
|
Paint(*this, rRect);
|
|
mpOutDevData->mpRecordLayout = nullptr;
|
|
}
|
|
|
|
void Window::DrawSelectionBackground( const Rectangle& rRect,
|
|
sal_uInt16 highlight,
|
|
bool bChecked,
|
|
bool bDrawBorder
|
|
)
|
|
{
|
|
if( rRect.IsEmpty() )
|
|
return;
|
|
|
|
const StyleSettings& rStyles = GetSettings().GetStyleSettings();
|
|
|
|
// colors used for item highlighting
|
|
Color aSelectionBorderCol( rStyles.GetHighlightColor() );
|
|
Color aSelectionFillCol( aSelectionBorderCol );
|
|
|
|
bool bDark = rStyles.GetFaceColor().IsDark();
|
|
bool bBright = ( rStyles.GetFaceColor() == Color( COL_WHITE ) );
|
|
|
|
int c1 = aSelectionBorderCol.GetLuminance();
|
|
int c2 = GetDisplayBackground().GetColor().GetLuminance();
|
|
|
|
if( !bDark && !bBright && abs( c2-c1 ) < 75 )
|
|
{
|
|
// constrast too low
|
|
sal_uInt16 h,s,b;
|
|
aSelectionFillCol.RGBtoHSB( h, s, b );
|
|
if( b > 50 ) b -= 40;
|
|
else b += 40;
|
|
aSelectionFillCol.SetColor( Color::HSBtoRGB( h, s, b ) );
|
|
aSelectionBorderCol = aSelectionFillCol;
|
|
}
|
|
|
|
Rectangle aRect( rRect );
|
|
Color oldFillCol = GetFillColor();
|
|
Color oldLineCol = GetLineColor();
|
|
|
|
if( bDrawBorder )
|
|
SetLineColor( bDark ? Color(COL_WHITE) : ( bBright ? Color(COL_BLACK) : aSelectionBorderCol ) );
|
|
else
|
|
SetLineColor();
|
|
|
|
sal_uInt16 nPercent = 0;
|
|
if( !highlight )
|
|
{
|
|
if( bDark )
|
|
aSelectionFillCol = COL_BLACK;
|
|
else
|
|
nPercent = 80; // just checked (light)
|
|
}
|
|
else
|
|
{
|
|
if( bChecked && highlight == 2 )
|
|
{
|
|
if( bDark )
|
|
aSelectionFillCol = COL_LIGHTGRAY;
|
|
else if ( bBright )
|
|
{
|
|
aSelectionFillCol = COL_BLACK;
|
|
SetLineColor( COL_BLACK );
|
|
nPercent = 0;
|
|
}
|
|
else
|
|
nPercent = 20; // selected, pressed or checked ( very dark )
|
|
}
|
|
else if( bChecked || highlight == 1 )
|
|
{
|
|
if( bDark )
|
|
aSelectionFillCol = COL_GRAY;
|
|
else if ( bBright )
|
|
{
|
|
aSelectionFillCol = COL_BLACK;
|
|
SetLineColor( COL_BLACK );
|
|
nPercent = 0;
|
|
}
|
|
else
|
|
nPercent = 35; // selected, pressed or checked ( very dark )
|
|
}
|
|
else
|
|
{
|
|
if( bDark )
|
|
aSelectionFillCol = COL_LIGHTGRAY;
|
|
else if ( bBright )
|
|
{
|
|
aSelectionFillCol = COL_BLACK;
|
|
SetLineColor( COL_BLACK );
|
|
if( highlight == 3 )
|
|
nPercent = 80;
|
|
else
|
|
nPercent = 0;
|
|
}
|
|
else
|
|
nPercent = 70; // selected ( dark )
|
|
}
|
|
}
|
|
|
|
SetFillColor( aSelectionFillCol );
|
|
|
|
if( bDark )
|
|
{
|
|
DrawRect( aRect );
|
|
}
|
|
else
|
|
{
|
|
tools::Polygon aPoly( aRect );
|
|
tools::PolyPolygon aPolyPoly( aPoly );
|
|
DrawTransparent( aPolyPoly, nPercent );
|
|
}
|
|
|
|
SetFillColor( oldFillCol );
|
|
SetLineColor( oldLineCol );
|
|
}
|
|
|
|
bool Window::IsScrollable() const
|
|
{
|
|
// check for scrollbars
|
|
vcl::Window *pChild = mpWindowImpl->mpFirstChild;
|
|
while( pChild )
|
|
{
|
|
if( pChild->GetType() == WINDOW_SCROLLBAR )
|
|
return true;
|
|
else
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Window::ImplMirrorFramePos( Point &pt ) const
|
|
{
|
|
pt.X() = mpWindowImpl->mpFrame->maGeometry.nWidth-1-pt.X();
|
|
}
|
|
|
|
// frame based modal counter (dialogs are not modal to the whole application anymore)
|
|
bool Window::IsInModalMode() const
|
|
{
|
|
return (mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mnModalMode != 0);
|
|
}
|
|
|
|
void Window::ImplIncModalCount()
|
|
{
|
|
vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
|
|
vcl::Window* pParent = pFrameWindow;
|
|
while( pFrameWindow )
|
|
{
|
|
pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode++;
|
|
while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
|
|
{
|
|
pParent = pParent->GetParent();
|
|
}
|
|
pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
|
|
}
|
|
}
|
|
void Window::ImplDecModalCount()
|
|
{
|
|
vcl::Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
|
|
vcl::Window* pParent = pFrameWindow;
|
|
while( pFrameWindow )
|
|
{
|
|
pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode--;
|
|
while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
|
|
{
|
|
pParent = pParent->GetParent();
|
|
}
|
|
pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow.get() : nullptr;
|
|
}
|
|
}
|
|
|
|
void Window::ImplIsInTaskPaneList( bool mbIsInTaskList )
|
|
{
|
|
mpWindowImpl->mbIsInTaskPaneList = mbIsInTaskList;
|
|
}
|
|
|
|
void Window::ImplNotifyIconifiedState( bool bIconified )
|
|
{
|
|
mpWindowImpl->mpFrameWindow->CallEventListeners( bIconified ? VCLEVENT_WINDOW_MINIMIZE : VCLEVENT_WINDOW_NORMALIZE );
|
|
// #109206# notify client window as well to have toolkit topwindow listeners notified
|
|
if( mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow && mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow )
|
|
mpWindowImpl->mpFrameWindow->mpWindowImpl->mpClientWindow->CallEventListeners( bIconified ? VCLEVENT_WINDOW_MINIMIZE : VCLEVENT_WINDOW_NORMALIZE );
|
|
}
|
|
|
|
bool Window::HasActiveChildFrame()
|
|
{
|
|
bool bRet = false;
|
|
vcl::Window *pFrameWin = ImplGetSVData()->maWinData.mpFirstFrame;
|
|
while( pFrameWin )
|
|
{
|
|
if( pFrameWin != mpWindowImpl->mpFrameWindow )
|
|
{
|
|
bool bDecorated = false;
|
|
vcl::Window *pChildFrame = pFrameWin->ImplGetWindow();
|
|
// #i15285# unfortunately WB_MOVEABLE is the same as WB_TABSTOP which can
|
|
// be removed for ToolBoxes to influence the keyboard accessibility
|
|
// thus WB_MOVEABLE is no indicator for decoration anymore
|
|
// but FloatingWindows carry this information in their TitleType...
|
|
// TODO: avoid duplicate WinBits !!!
|
|
if( pChildFrame && pChildFrame->ImplIsFloatingWindow() )
|
|
bDecorated = static_cast<FloatingWindow*>(pChildFrame)->GetTitleType() != FloatWinTitleType::NONE;
|
|
if( bDecorated || (pFrameWin->mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) ) )
|
|
if( pChildFrame && pChildFrame->IsVisible() && pChildFrame->IsActive() )
|
|
{
|
|
if( ImplIsChild( pChildFrame, true ) )
|
|
{
|
|
bRet = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
LanguageType Window::GetInputLanguage() const
|
|
{
|
|
return mpWindowImpl->mpFrame->GetInputLanguage();
|
|
}
|
|
|
|
void Window::EnableNativeWidget( bool bEnable )
|
|
{
|
|
static const char* pNoNWF = getenv( "SAL_NO_NWF" );
|
|
if( pNoNWF && *pNoNWF )
|
|
bEnable = false;
|
|
|
|
if( bEnable != ImplGetWinData()->mbEnableNativeWidget )
|
|
{
|
|
ImplGetWinData()->mbEnableNativeWidget = bEnable;
|
|
|
|
// send datachanged event to allow for internal changes required for NWF
|
|
// like clipmode, transparency, etc.
|
|
DataChangedEvent aDCEvt( DataChangedEventType::SETTINGS, mxSettings.get(), AllSettingsFlags::STYLE );
|
|
CompatDataChanged( aDCEvt );
|
|
|
|
// sometimes the borderwindow is queried, so keep it in sync
|
|
if( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->ImplGetWinData()->mbEnableNativeWidget = bEnable;
|
|
}
|
|
|
|
// push down, useful for compound controls
|
|
vcl::Window *pChild = mpWindowImpl->mpFirstChild;
|
|
while( pChild )
|
|
{
|
|
pChild->EnableNativeWidget( bEnable );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
bool Window::IsNativeWidgetEnabled() const
|
|
{
|
|
return ImplGetWinData()->mbEnableNativeWidget;
|
|
}
|
|
|
|
Reference< css::rendering::XCanvas > Window::ImplGetCanvas( bool bSpriteCanvas ) const
|
|
{
|
|
// try to retrieve hard reference from weak member
|
|
Reference< css::rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
|
|
|
|
// canvas still valid? Then we're done.
|
|
if( xCanvas.is() )
|
|
return xCanvas;
|
|
|
|
Sequence< Any > aArg(6);
|
|
|
|
// Feed any with operating system's window handle
|
|
|
|
// common: first any is VCL pointer to window (for VCL canvas)
|
|
aArg[ 0 ] = makeAny( reinterpret_cast<sal_Int64>(this) );
|
|
aArg[ 1 ] = GetSystemDataAny();
|
|
aArg[ 2 ] = makeAny( css::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ) );
|
|
aArg[ 3 ] = makeAny( mpWindowImpl->mbAlwaysOnTop );
|
|
aArg[ 4 ] = makeAny( Reference< css::awt::XWindow >(
|
|
const_cast<vcl::Window*>(this)->GetComponentInterface(),
|
|
UNO_QUERY ));
|
|
aArg[ 5 ] = GetSystemGfxDataAny();
|
|
|
|
Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
|
|
|
|
// Create canvas instance with window handle
|
|
|
|
static vcl::DeleteUnoReferenceOnDeinit<XMultiComponentFactory> xStaticCanvasFactory(
|
|
css::rendering::CanvasFactory::create( xContext ) );
|
|
Reference<XMultiComponentFactory> xCanvasFactory(xStaticCanvasFactory.get());
|
|
|
|
if(xCanvasFactory.is())
|
|
{
|
|
#ifdef _WIN32
|
|
// see #140456# - if we're running on a multiscreen setup,
|
|
// request special, multi-screen safe sprite canvas
|
|
// implementation (not DX5 canvas, as it cannot cope with
|
|
// surfaces spanning multiple displays). Note: canvas
|
|
// (without sprite) stays the same)
|
|
const sal_uInt32 nDisplay = static_cast< WinSalFrame* >( mpWindowImpl->mpFrame )->mnDisplay;
|
|
if( (nDisplay >= Application::GetScreenCount()) )
|
|
{
|
|
xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
|
|
bSpriteCanvas ?
|
|
OUString( "com.sun.star.rendering.SpriteCanvas.MultiScreen" ) :
|
|
OUString( "com.sun.star.rendering.Canvas.MultiScreen" ),
|
|
aArg,
|
|
xContext ),
|
|
UNO_QUERY );
|
|
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
xCanvas.set( xCanvasFactory->createInstanceWithArgumentsAndContext(
|
|
bSpriteCanvas ?
|
|
OUString( "com.sun.star.rendering.SpriteCanvas" ) :
|
|
OUString( "com.sun.star.rendering.Canvas" ),
|
|
aArg,
|
|
xContext ),
|
|
UNO_QUERY );
|
|
|
|
#ifdef _WIN32
|
|
}
|
|
#endif
|
|
mpWindowImpl->mxCanvas = xCanvas;
|
|
}
|
|
|
|
// no factory??? Empty reference, then.
|
|
return xCanvas;
|
|
}
|
|
|
|
Reference< css::rendering::XCanvas > Window::GetCanvas() const
|
|
{
|
|
return ImplGetCanvas( false );
|
|
}
|
|
|
|
Reference< css::rendering::XSpriteCanvas > Window::GetSpriteCanvas() const
|
|
{
|
|
Reference< css::rendering::XSpriteCanvas > xSpriteCanvas(
|
|
ImplGetCanvas( true ), UNO_QUERY );
|
|
return xSpriteCanvas;
|
|
}
|
|
|
|
OUString Window::GetSurroundingText() const
|
|
{
|
|
return OUString();
|
|
}
|
|
|
|
Selection Window::GetSurroundingTextSelection() const
|
|
{
|
|
return Selection( 0, 0 );
|
|
}
|
|
|
|
bool Window::UsePolyPolygonForComplexGradient()
|
|
{
|
|
if ( meRasterOp != RasterOp::OverPaint )
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void Window::ApplySettings(vcl::RenderContext& /*rRenderContext*/)
|
|
{
|
|
}
|
|
|
|
const SystemEnvData* Window::GetSystemData() const
|
|
{
|
|
|
|
return mpWindowImpl->mpFrame ? mpWindowImpl->mpFrame->GetSystemData() : nullptr;
|
|
}
|
|
|
|
Any Window::GetSystemDataAny() const
|
|
{
|
|
Any aRet;
|
|
const SystemEnvData* pSysData = GetSystemData();
|
|
if( pSysData )
|
|
{
|
|
Sequence< sal_Int8 > aSeq( reinterpret_cast<sal_Int8 const *>(pSysData), pSysData->nSize );
|
|
aRet <<= aSeq;
|
|
}
|
|
return aRet;
|
|
}
|
|
|
|
bool Window::SupportsDoubleBuffering() const
|
|
{
|
|
return mpWindowImpl->mpFrameData->mpBuffer;
|
|
}
|
|
|
|
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 rational here is that we moved destructors to
|
|
* dispose and this altered a lot of code paths, that
|
|
* are better left unchanged for now.
|
|
*/
|
|
#define COMPAT_BODY(method,args) \
|
|
if (!mpWindowImpl || mpWindowImpl->mbInDispose) \
|
|
Window::method args; \
|
|
else \
|
|
method args;
|
|
|
|
void Window::CompatGetFocus()
|
|
{
|
|
COMPAT_BODY(GetFocus,())
|
|
}
|
|
|
|
void Window::CompatLoseFocus()
|
|
{
|
|
COMPAT_BODY(LoseFocus,())
|
|
}
|
|
|
|
void Window::CompatStateChanged( StateChangedType nStateChange )
|
|
{
|
|
COMPAT_BODY(StateChanged,(nStateChange))
|
|
}
|
|
|
|
void Window::CompatDataChanged( const DataChangedEvent& rDCEvt )
|
|
{
|
|
COMPAT_BODY(DataChanged,(rDCEvt))
|
|
}
|
|
|
|
bool Window::CompatPreNotify( NotifyEvent& rNEvt )
|
|
{
|
|
if (!mpWindowImpl || mpWindowImpl->mbInDispose)
|
|
return Window::PreNotify( rNEvt );
|
|
else
|
|
return PreNotify( rNEvt );
|
|
}
|
|
|
|
bool Window::CompatNotify( NotifyEvent& rNEvt )
|
|
{
|
|
if (!mpWindowImpl || mpWindowImpl->mbInDispose)
|
|
return Window::Notify( rNEvt );
|
|
else
|
|
return Notify( rNEvt );
|
|
}
|
|
|
|
void Window::set_id(const OUString& rID)
|
|
{
|
|
mpWindowImpl->maID = rID;
|
|
}
|
|
|
|
const OUString& Window::get_id() const
|
|
{
|
|
return mpWindowImpl->maID;
|
|
}
|
|
|
|
FactoryFunction Window::GetUITestFactory() const
|
|
{
|
|
return WindowUIObject::create;
|
|
}
|
|
|
|
} /* namespace vcl */
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|