Nah, seems that it was used after all on Windows, somehow. This reverts commit 5754264f93001978a3c5f5f1cdabd7113de010b8.
9709 lines
343 KiB
C++
9709 lines
343 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 <i18npool/mslangid.hxx>
|
|
|
|
#include "tools/time.hxx"
|
|
#include "tools/debug.hxx"
|
|
#include "tools/rc.h"
|
|
|
|
#include "unotools/fontcfg.hxx"
|
|
#include "unotools/confignode.hxx"
|
|
|
|
#include "vcl/layout.hxx"
|
|
#include "vcl/salgtype.hxx"
|
|
#include "vcl/event.hxx"
|
|
#include "vcl/fixed.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/menu.hxx"
|
|
#include "vcl/wrkwin.hxx"
|
|
#include "vcl/wall.hxx"
|
|
#include "vcl/gradient.hxx"
|
|
#include "vcl/salctype.hxx"
|
|
#include "vcl/button.hxx"
|
|
#include "vcl/taskpanelist.hxx"
|
|
#include "vcl/dialog.hxx"
|
|
#include "vcl/unowrap.hxx"
|
|
#include "vcl/gdimtf.hxx"
|
|
#include "vcl/pdfextoutdevdata.hxx"
|
|
#include "vcl/popupmenuwindow.hxx"
|
|
#include "vcl/lazydelete.hxx"
|
|
#include "vcl/virdev.hxx"
|
|
|
|
// declare system types in sysdata.hxx
|
|
#include "svsys.h"
|
|
#include "vcl/sysdata.hxx"
|
|
|
|
#include "salframe.hxx"
|
|
#include "salobj.hxx"
|
|
#include "salinst.hxx"
|
|
#include "salgdi.hxx"
|
|
#include "svdata.hxx"
|
|
#include "dbggui.hxx"
|
|
#include "outfont.hxx"
|
|
#include "window.h"
|
|
#include "toolbox.h"
|
|
#include "outdev.h"
|
|
#include "region.h"
|
|
#include "brdwin.hxx"
|
|
#include "helpwin.hxx"
|
|
#include "sallayout.hxx"
|
|
#include "dndlcon.hxx"
|
|
#include "dndevdis.hxx"
|
|
|
|
#include "com/sun/star/awt/XWindowPeer.hpp"
|
|
#include "com/sun/star/rendering/XCanvas.hpp"
|
|
#include "com/sun/star/rendering/XSpriteCanvas.hpp"
|
|
#include "com/sun/star/awt/XWindow.hpp"
|
|
#include "comphelper/processfactory.hxx"
|
|
#include "com/sun/star/datatransfer/dnd/XDragSource.hpp"
|
|
#include "com/sun/star/datatransfer/dnd/XDropTarget.hpp"
|
|
#include "com/sun/star/datatransfer/clipboard/XClipboard.hpp"
|
|
#include "com/sun/star/datatransfer/clipboard/SystemClipboard.hpp"
|
|
#include "com/sun/star/awt/XTopWindow.hpp"
|
|
#include "com/sun/star/awt/XDisplayConnection.hpp"
|
|
#include "com/sun/star/lang/XInitialization.hpp"
|
|
#include "com/sun/star/lang/XComponent.hpp"
|
|
#include "com/sun/star/lang/XServiceName.hpp"
|
|
#include "com/sun/star/accessibility/XAccessible.hpp"
|
|
#include "com/sun/star/accessibility/AccessibleRole.hpp"
|
|
|
|
#include <sal/macros.h>
|
|
#include <rtl/strbuf.hxx>
|
|
|
|
#include <set>
|
|
#include <typeinfo>
|
|
|
|
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;
|
|
using namespace ::com::sun::star;
|
|
using namespace com::sun;
|
|
|
|
using ::rtl::OUString;
|
|
|
|
using ::com::sun::star::awt::XTopWindow;
|
|
|
|
// =======================================================================
|
|
|
|
DBG_NAME( Window )
|
|
|
|
// =======================================================================
|
|
|
|
#define IMPL_PAINT_PAINT ((sal_uInt16)0x0001)
|
|
#define IMPL_PAINT_PAINTALL ((sal_uInt16)0x0002)
|
|
#define IMPL_PAINT_PAINTALLCHILDREN ((sal_uInt16)0x0004)
|
|
#define IMPL_PAINT_PAINTCHILDREN ((sal_uInt16)0x0008)
|
|
#define IMPL_PAINT_ERASE ((sal_uInt16)0x0010)
|
|
#define IMPL_PAINT_CHECKRTL ((sal_uInt16)0x0020)
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
struct ImplCalcToTopData
|
|
{
|
|
ImplCalcToTopData* mpNext;
|
|
Window* mpWindow;
|
|
Region* mpInvalidateRegion;
|
|
};
|
|
|
|
ImplAccessibleInfos::ImplAccessibleInfos()
|
|
{
|
|
nAccessibleRole = 0xFFFF;
|
|
pAccessibleName = NULL;
|
|
pAccessibleDescription = NULL;
|
|
pLabeledByWindow = NULL;
|
|
pLabelForWindow = NULL;
|
|
pMemberOfWindow = NULL;
|
|
}
|
|
|
|
ImplAccessibleInfos::~ImplAccessibleInfos()
|
|
{
|
|
delete pAccessibleName;
|
|
delete pAccessibleDescription;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
WindowImpl::WindowImpl()
|
|
{
|
|
}
|
|
|
|
WindowImpl::~WindowImpl()
|
|
{
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// helper method to allow inline constructor even for pWindow!=NULL case
|
|
void ImplDelData::AttachToWindow( const Window* pWindow )
|
|
{
|
|
if( pWindow )
|
|
const_cast<Window*>(pWindow)->ImplAddDel( this );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// define dtor for ImplDelData
|
|
ImplDelData::~ImplDelData()
|
|
{
|
|
// #112873# auto remove of ImplDelData
|
|
// due to this code actively calling ImplRemoveDel() is not mandatory anymore
|
|
if( !mbDel && mpWindow )
|
|
{
|
|
// the window still exists but we were not removed
|
|
const_cast<Window*>(mpWindow)->ImplRemoveDel( this );
|
|
mpWindow = NULL;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
#ifdef DBG_UTIL
|
|
const char* ImplDbgCheckWindow( const void* pObj )
|
|
{
|
|
DBG_TESTSOLARMUTEX();
|
|
|
|
const Window* pWindow = (Window*)pObj;
|
|
|
|
if ( (pWindow->GetType() < WINDOW_FIRST) || (pWindow->GetType() > WINDOW_LAST) )
|
|
return "Window data overwrite";
|
|
|
|
// check window-chain
|
|
Window* pChild = pWindow->mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
if ( pChild->mpWindowImpl->mpParent != pWindow )
|
|
return "Child-Window-Parent wrong";
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
// =======================================================================
|
|
|
|
void Window::ImplInitAppFontData( 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;
|
|
|
|
// FIXME: this is currently only on aqua, 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( CTRL_EDITBOX, PART_ENTIRE_CONTROL, aCtrlRegion,
|
|
CTRL_STATE_ENABLED, aControlValue, rtl::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;
|
|
}
|
|
}
|
|
|
|
|
|
pSVData->maGDIData.mnRealAppFontX = pSVData->maGDIData.mnAppFontX;
|
|
if ( pSVData->maAppData.mnDialogScaleX )
|
|
pSVData->maGDIData.mnAppFontX += (pSVData->maGDIData.mnAppFontX*pSVData->maAppData.mnDialogScaleX)/100;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
bool Window::ImplCheckUIFont( const Font& rFont )
|
|
{
|
|
if( ImplGetSVData()->maGDIData.mbNativeFontConfig )
|
|
return true;
|
|
|
|
// create a text string using the localized text of important buttons
|
|
String aTestText;
|
|
static const StandardButtonType aTestButtons[] =
|
|
{
|
|
BUTTON_OK, BUTTON_CANCEL, BUTTON_CLOSE, BUTTON_ABORT,
|
|
BUTTON_YES, BUTTON_NO, BUTTON_MORE, BUTTON_IGNORE,
|
|
BUTTON_RETRY, BUTTON_HELP
|
|
};
|
|
|
|
const int nTestButtonCount = SAL_N_ELEMENTS(aTestButtons);
|
|
for( int n = 0; n < nTestButtonCount; ++n )
|
|
{
|
|
String aButtonStr = Button::GetStandardText( aTestButtons[n] );
|
|
// #i115432# ignore mnemonic+accelerator part of each string
|
|
// TODO: use a string filtering method when it becomes available
|
|
const int nLen = aButtonStr.Len();
|
|
bool bInside = false;
|
|
for( int i = 0; i < nLen; ++i ) {
|
|
const sal_Unicode c = aButtonStr.GetChar( i );
|
|
if( (c == '('))
|
|
bInside = true;
|
|
if( (c == ')'))
|
|
bInside = false;
|
|
if( (c == '~')
|
|
|| (c == '(') || (c == ')')
|
|
|| ((c >= 'A') && (c <= 'Z') && bInside) )
|
|
aButtonStr.SetChar( i, ' ' );
|
|
}
|
|
// append sanitized button text to test string
|
|
aTestText.Append( aButtonStr );
|
|
}
|
|
|
|
const int nFirstChar = HasGlyphs( rFont, aTestText );
|
|
const bool bUIFontOk = (nFirstChar >= aTestText.Len());
|
|
return bUIFontOk;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplUpdateGlobalSettings( AllSettings& rSettings, sal_Bool bCallHdl )
|
|
{
|
|
StyleSettings aTmpSt( rSettings.GetStyleSettings() );
|
|
aTmpSt.SetHighContrastMode( sal_False );
|
|
rSettings.SetStyleSettings( aTmpSt );
|
|
ImplGetFrame()->UpdateSettings( rSettings );
|
|
// reset default border width for layouters
|
|
ImplGetSVData()->maAppData.mnDefaultLayoutBorder = -1;
|
|
|
|
// Verify availability of the configured UI font, otherwise choose "Andale Sans UI"
|
|
String aUserInterfaceFont;
|
|
bool bUseSystemFont = rSettings.GetStyleSettings().GetUseSystemUIFonts();
|
|
|
|
// check whether system UI font can display a typical UI text
|
|
if( bUseSystemFont )
|
|
bUseSystemFont = ImplCheckUIFont( rSettings.GetStyleSettings().GetAppFont() );
|
|
|
|
if ( !bUseSystemFont )
|
|
{
|
|
ImplInitFontList();
|
|
String aConfigFont = utl::DefaultFontConfiguration::get().getUserInterfaceFont( rSettings.GetUILanguageTag().getLocale() );
|
|
xub_StrLen nIndex = 0;
|
|
while( nIndex != STRING_NOTFOUND )
|
|
{
|
|
String aName( aConfigFont.GetToken( 0, ';', nIndex ) );
|
|
if ( aName.Len() && mpWindowImpl->mpFrameData->mpFontList->FindFontFamily( aName ) )
|
|
{
|
|
aUserInterfaceFont = aConfigFont;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( ! aUserInterfaceFont.Len() )
|
|
{
|
|
String aFallbackFont ("Andale Sans UI" );
|
|
if ( mpWindowImpl->mpFrameData->mpFontList->FindFontFamily( aFallbackFont ) )
|
|
aUserInterfaceFont = aFallbackFont;
|
|
}
|
|
}
|
|
|
|
if ( !bUseSystemFont && aUserInterfaceFont.Len() )
|
|
{
|
|
StyleSettings aStyleSettings = rSettings.GetStyleSettings();
|
|
Font aFont = aStyleSettings.GetAppFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetAppFont( aFont );
|
|
aFont = aStyleSettings.GetHelpFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetHelpFont( aFont );
|
|
aFont = aStyleSettings.GetTitleFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetTitleFont( aFont );
|
|
aFont = aStyleSettings.GetFloatTitleFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetFloatTitleFont( aFont );
|
|
aFont = aStyleSettings.GetMenuFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetMenuFont( aFont );
|
|
aFont = aStyleSettings.GetToolFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetToolFont( aFont );
|
|
aFont = aStyleSettings.GetLabelFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetLabelFont( aFont );
|
|
aFont = aStyleSettings.GetInfoFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetInfoFont( aFont );
|
|
aFont = aStyleSettings.GetRadioCheckFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetRadioCheckFont( aFont );
|
|
aFont = aStyleSettings.GetPushButtonFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetPushButtonFont( aFont );
|
|
aFont = aStyleSettings.GetFieldFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetFieldFont( aFont );
|
|
aFont = aStyleSettings.GetIconFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetIconFont( aFont );
|
|
aFont = aStyleSettings.GetGroupFont();
|
|
aFont.SetName( aUserInterfaceFont );
|
|
aStyleSettings.SetGroupFont( aFont );
|
|
rSettings.SetStyleSettings( aStyleSettings );
|
|
}
|
|
|
|
StyleSettings aStyleSettings = rSettings.GetStyleSettings();
|
|
// #97047: Force all fonts except Menu and Help to a fixed height
|
|
// to avoid UI scaling due to large fonts
|
|
// - but allow bigger fonts on bigger screens (i16682, i21238)
|
|
// dialogs were designed to fit 800x600 with an 8pt font, so scale accordingly
|
|
int maxFontheight = 9; // #107886#: 9 is default for some asian systems, so always allow if requested
|
|
if( GetDesktopRectPixel().getHeight() > 600 )
|
|
maxFontheight = (int) ((( 8.0 * (double) GetDesktopRectPixel().getHeight()) / 600.0) + 1.5);
|
|
|
|
Font aFont = aStyleSettings.GetMenuFont();
|
|
int defFontheight = aFont.GetHeight();
|
|
if( defFontheight > maxFontheight )
|
|
defFontheight = maxFontheight;
|
|
|
|
// if the UI is korean, chinese or another locale
|
|
// where the system font size is kown to be often too small to
|
|
// generate readable fonts enforce a minimum font size of 9 points
|
|
bool bBrokenLangFontHeight = MsLangId::isCJK(Application::GetSettings().GetUILanguageTag().getLanguageType());
|
|
if (bBrokenLangFontHeight)
|
|
defFontheight = Max(9, defFontheight);
|
|
|
|
// i22098, toolfont will be scaled differently to avoid bloated rulers and status bars for big fonts
|
|
int toolfontheight = defFontheight;
|
|
if( toolfontheight > 9 )
|
|
toolfontheight = (defFontheight+8) / 2;
|
|
|
|
aFont = aStyleSettings.GetAppFont();
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetAppFont( aFont );
|
|
aFont = aStyleSettings.GetTitleFont();
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetTitleFont( aFont );
|
|
aFont = aStyleSettings.GetFloatTitleFont();
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetFloatTitleFont( aFont );
|
|
// keep menu and help font size from system unless in broken locale size
|
|
if( bBrokenLangFontHeight )
|
|
{
|
|
aFont = aStyleSettings.GetMenuFont();
|
|
if( aFont.GetHeight() < defFontheight )
|
|
{
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetMenuFont( aFont );
|
|
}
|
|
aFont = aStyleSettings.GetHelpFont();
|
|
if( aFont.GetHeight() < defFontheight )
|
|
{
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetHelpFont( aFont );
|
|
}
|
|
}
|
|
|
|
// use different height for toolfont
|
|
aFont = aStyleSettings.GetToolFont();
|
|
aFont.SetHeight( toolfontheight );
|
|
aStyleSettings.SetToolFont( aFont );
|
|
|
|
aFont = aStyleSettings.GetLabelFont();
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetLabelFont( aFont );
|
|
aFont = aStyleSettings.GetInfoFont();
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetInfoFont( aFont );
|
|
aFont = aStyleSettings.GetRadioCheckFont();
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetRadioCheckFont( aFont );
|
|
aFont = aStyleSettings.GetPushButtonFont();
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetPushButtonFont( aFont );
|
|
aFont = aStyleSettings.GetFieldFont();
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetFieldFont( aFont );
|
|
aFont = aStyleSettings.GetIconFont();
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetIconFont( aFont );
|
|
aFont = aStyleSettings.GetGroupFont();
|
|
aFont.SetHeight( defFontheight );
|
|
aStyleSettings.SetGroupFont( aFont );
|
|
|
|
// set workspace gradient to black in dark themes
|
|
if( aStyleSettings.GetWindowColor().IsDark() )
|
|
aStyleSettings.SetWorkspaceGradient( Wallpaper( Color( COL_BLACK ) ) );
|
|
else
|
|
{
|
|
Gradient aGrad( GradientStyle_LINEAR, DEFAULT_WORKSPACE_GRADIENT_START_COLOR, DEFAULT_WORKSPACE_GRADIENT_END_COLOR );
|
|
aStyleSettings.SetWorkspaceGradient( Wallpaper( aGrad ) );
|
|
}
|
|
|
|
rSettings.SetStyleSettings( aStyleSettings );
|
|
|
|
// auto detect HC mode; if the system already set it to "yes"
|
|
// (see above) then accept that
|
|
if( !rSettings.GetStyleSettings().GetHighContrastMode() )
|
|
{
|
|
sal_Bool bTmp = sal_False, bAutoHCMode = sal_True;
|
|
utl::OConfigurationNode aNode = utl::OConfigurationTreeRoot::tryCreateWithComponentContext(
|
|
comphelper::getProcessComponentContext(),
|
|
OUString("org.openoffice.Office.Common/Accessibility") ); // note: case sensitive !
|
|
if ( aNode.isValid() )
|
|
{
|
|
::com::sun::star::uno::Any aValue = aNode.getNodeValue( OUString("AutoDetectSystemHC") );
|
|
if( aValue >>= bTmp )
|
|
bAutoHCMode = bTmp;
|
|
}
|
|
if( bAutoHCMode )
|
|
{
|
|
if( rSettings.GetStyleSettings().GetFaceColor().IsDark()
|
|
|| rSettings.GetStyleSettings().GetWindowColor().IsDark() )
|
|
{
|
|
aStyleSettings = rSettings.GetStyleSettings();
|
|
aStyleSettings.SetHighContrastMode( sal_True );
|
|
aStyleSettings.SetSymbolsStyle( STYLE_SYMBOLS_HICONTRAST );
|
|
rSettings.SetStyleSettings( aStyleSettings );
|
|
}
|
|
}
|
|
}
|
|
|
|
static const char* pEnvHC = getenv( "SAL_FORCE_HC" );
|
|
if( pEnvHC && *pEnvHC )
|
|
{
|
|
aStyleSettings.SetHighContrastMode( sal_True );
|
|
aStyleSettings.SetSymbolsStyle( STYLE_SYMBOLS_HICONTRAST );
|
|
rSettings.SetStyleSettings( aStyleSettings );
|
|
}
|
|
|
|
#if defined(DBG_UTIL)
|
|
// If needed, set AppFont to bold, in order to check
|
|
// if there is enough space available for texts on other systems
|
|
if ( DbgIsBoldAppFont() )
|
|
{
|
|
aStyleSettings = rSettings.GetStyleSettings();
|
|
aFont = aStyleSettings.GetAppFont();
|
|
aFont.SetWeight( WEIGHT_BOLD );
|
|
aStyleSettings.SetAppFont( aFont );
|
|
aFont = aStyleSettings.GetGroupFont();
|
|
aFont.SetWeight( WEIGHT_BOLD );
|
|
aStyleSettings.SetGroupFont( aFont );
|
|
aFont = aStyleSettings.GetLabelFont();
|
|
aFont.SetWeight( WEIGHT_BOLD );
|
|
aStyleSettings.SetLabelFont( aFont );
|
|
aFont = aStyleSettings.GetRadioCheckFont();
|
|
aFont.SetWeight( WEIGHT_BOLD );
|
|
aStyleSettings.SetRadioCheckFont( aFont );
|
|
aFont = aStyleSettings.GetPushButtonFont();
|
|
aFont.SetWeight( WEIGHT_BOLD );
|
|
aStyleSettings.SetPushButtonFont( aFont );
|
|
aFont = aStyleSettings.GetFieldFont();
|
|
aFont.SetWeight( WEIGHT_BOLD );
|
|
aStyleSettings.SetFieldFont( aFont );
|
|
aFont = aStyleSettings.GetIconFont();
|
|
aFont.SetWeight( WEIGHT_BOLD );
|
|
aStyleSettings.SetIconFont( aFont );
|
|
rSettings.SetStyleSettings( aStyleSettings );
|
|
}
|
|
#endif
|
|
|
|
if ( bCallHdl )
|
|
GetpApp()->SystemSettingsChanging( rSettings, this );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
MouseEvent ImplTranslateMouseEvent( const MouseEvent& rE, Window* pSource, Window* pDest )
|
|
{
|
|
Point aPos = pSource->OutputToScreenPixel( rE.GetPosPixel() );
|
|
aPos = pDest->ScreenToOutputPixel( aPos );
|
|
return MouseEvent( aPos, rE.GetClicks(), rE.GetMode(), rE.GetButtons(), rE.GetModifier() );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
CommandEvent ImplTranslateCommandEvent( const CommandEvent& rCEvt, Window* pSource, Window* pDest )
|
|
{
|
|
if ( !rCEvt.IsMouseEvent() )
|
|
return rCEvt;
|
|
|
|
Point aPos = pSource->OutputToScreenPixel( rCEvt.GetMousePosPixel() );
|
|
aPos = pDest->ScreenToOutputPixel( aPos );
|
|
return CommandEvent( aPos, rCEvt.GetCommand(), rCEvt.IsMouseEvent(), rCEvt.GetData() );
|
|
}
|
|
|
|
// =======================================================================
|
|
|
|
void Window::ImplInitWindowData( WindowType nType )
|
|
{
|
|
mpWindowImpl = new WindowImpl;
|
|
|
|
meOutDevType = OUTDEV_WINDOW;
|
|
|
|
mpWindowImpl->maZoom = Fraction( 1, 1 );
|
|
mpWindowImpl->maWinRegion = Region( REGION_NULL );
|
|
mpWindowImpl->maWinClipRegion = Region( REGION_NULL );
|
|
mpWindowImpl->mpWinData = NULL; // Extra Window Data, that we dont need for all windows
|
|
mpWindowImpl->mpOverlapData = NULL; // Overlap Data
|
|
mpWindowImpl->mpFrameData = NULL; // Frame Data
|
|
mpWindowImpl->mpFrame = NULL; // Pointer to frame window
|
|
mpWindowImpl->mpSysObj = NULL;
|
|
mpWindowImpl->mpFrameWindow = NULL; // window to top level parent (same as frame window)
|
|
mpWindowImpl->mpOverlapWindow = NULL; // first overlap parent
|
|
mpWindowImpl->mpBorderWindow = NULL; // Border-Window
|
|
mpWindowImpl->mpClientWindow = NULL; // Client-Window of a FrameWindow
|
|
mpWindowImpl->mpParent = NULL; // parent (inkl. BorderWindow)
|
|
mpWindowImpl->mpRealParent = NULL; // real parent (exkl. BorderWindow)
|
|
mpWindowImpl->mpFirstChild = NULL; // first child window
|
|
mpWindowImpl->mpLastChild = NULL; // last child window
|
|
mpWindowImpl->mpFirstOverlap = NULL; // first overlap window (only set in overlap windows)
|
|
mpWindowImpl->mpLastOverlap = NULL; // last overlap window (only set in overlap windows)
|
|
mpWindowImpl->mpPrev = NULL; // prev window
|
|
mpWindowImpl->mpNext = NULL; // next window
|
|
mpWindowImpl->mpNextOverlap = NULL; // next overlap window of frame
|
|
mpWindowImpl->mpLastFocusWindow = NULL; // window for focus restore
|
|
mpWindowImpl->mpDlgCtrlDownWindow = NULL; // window for dialog control
|
|
mpWindowImpl->mpFirstDel = NULL; // Dtor notification list
|
|
mpWindowImpl->mpUserData = NULL; // user data
|
|
mpWindowImpl->mpCursor = NULL; // cursor
|
|
mpWindowImpl->mpControlFont = NULL; // font propertie
|
|
mpWindowImpl->mpVCLXWindow = NULL;
|
|
mpWindowImpl->mpAccessibleInfos = NULL;
|
|
mpWindowImpl->maControlForeground = Color( COL_TRANSPARENT ); // no foreground set
|
|
mpWindowImpl->maControlBackground = Color( COL_TRANSPARENT ); // no background set
|
|
mpWindowImpl->mnLeftBorder = 0; // left border
|
|
mpWindowImpl->mnTopBorder = 0; // top border
|
|
mpWindowImpl->mnRightBorder = 0; // right border
|
|
mpWindowImpl->mnBottomBorder = 0; // bottom border
|
|
mpWindowImpl->mnWidthRequest = -1; // width request
|
|
mpWindowImpl->mnHeightRequest = -1; // height request
|
|
mpWindowImpl->mnX = 0; // X-Position to Parent
|
|
mpWindowImpl->mnY = 0; // Y-Position to Parent
|
|
mpWindowImpl->mnAbsScreenX = 0; // absolute X-position on screen, used for RTL window positioning
|
|
mpWindowImpl->mpChildClipRegion = NULL; // Child-Clip-Region when ClipChildren
|
|
mpWindowImpl->mpPaintRegion = NULL; // Paint-ClipRegion
|
|
mpWindowImpl->mnStyle = 0; // style (init in ImplInitWindow)
|
|
mpWindowImpl->mnPrevStyle = 0; // prevstyle (set in SetStyle)
|
|
mpWindowImpl->mnExtendedStyle = 0; // extended style (init in ImplInitWindow)
|
|
mpWindowImpl->mnPrevExtendedStyle = 0; // prevstyle (set in SetExtendedStyle)
|
|
mpWindowImpl->mnType = nType; // type
|
|
mpWindowImpl->mnGetFocusFlags = 0; // Flags fuer GetFocus()-Aufruf
|
|
mpWindowImpl->mnWaitCount = 0; // Wait-Count (>1 == Warte-MousePointer)
|
|
mpWindowImpl->mnPaintFlags = 0; // Flags for ImplCallPaint
|
|
mpWindowImpl->mnParentClipMode = 0; // Flags for Parent-ClipChildren-Mode
|
|
mpWindowImpl->mnActivateMode = 0; // Will be converted in System/Overlap-Windows
|
|
mpWindowImpl->mnDlgCtrlFlags = 0; // DialogControl-Flags
|
|
mpWindowImpl->mnLockCount = 0; // LockCount
|
|
mpWindowImpl->meAlwaysInputMode = AlwaysInputNone; // neither AlwaysEnableInput nor AlwaysDisableInput called
|
|
mpWindowImpl->meHalign = VCL_ALIGN_FILL;
|
|
mpWindowImpl->meValign = VCL_ALIGN_FILL;
|
|
mpWindowImpl->mePackType = VCL_PACK_START;
|
|
mpWindowImpl->mnPadding = 0;
|
|
mpWindowImpl->mnGridHeight = 1;
|
|
mpWindowImpl->mnGridLeftAttach = -1;
|
|
mpWindowImpl->mnGridTopAttach = -1;
|
|
mpWindowImpl->mnGridWidth = 1;
|
|
mpWindowImpl->mnBorderWidth = 0;
|
|
mpWindowImpl->mnMarginLeft = 0;
|
|
mpWindowImpl->mnMarginRight = 0;
|
|
mpWindowImpl->mnMarginTop = 0;
|
|
mpWindowImpl->mnMarginBottom = 0;
|
|
mpWindowImpl->mbFrame = sal_False; // sal_True: Window is a frame window
|
|
mpWindowImpl->mbBorderWin = sal_False; // sal_True: Window is a border window
|
|
mpWindowImpl->mbOverlapWin = sal_False; // sal_True: Window is a overlap window
|
|
mpWindowImpl->mbSysWin = sal_False; // sal_True: SystemWindow is the base class
|
|
mpWindowImpl->mbDialog = sal_False; // sal_True: Dialog is the base class
|
|
mpWindowImpl->mbDockWin = sal_False; // sal_True: DockingWindow is the base class
|
|
mpWindowImpl->mbFloatWin = sal_False; // sal_True: FloatingWindow is the base class
|
|
mpWindowImpl->mbPushButton = sal_False; // sal_True: PushButton is the base class
|
|
mpWindowImpl->mbToolBox = sal_False; // sal_True: ToolBox is the base class
|
|
mpWindowImpl->mbMenuFloatingWindow= sal_False; // sal_True: MenuFloatingWindow is the base class
|
|
mpWindowImpl->mbToolbarFloatingWindow= sal_False; // sal_True: ImplPopupFloatWin is the base class, used for subtoolbars
|
|
mpWindowImpl->mbSplitter = sal_False; // sal_True: Splitter is the base class
|
|
mpWindowImpl->mbVisible = sal_False; // sal_True: Show( sal_True ) called
|
|
mpWindowImpl->mbOverlapVisible = sal_False; // sal_True: Hide called for visible window from ImplHideAllOverlapWindow()
|
|
mpWindowImpl->mbDisabled = sal_False; // sal_True: Enable( sal_False ) called
|
|
mpWindowImpl->mbInputDisabled = sal_False; // sal_True: EnableInput( sal_False ) called
|
|
mpWindowImpl->mbDropDisabled = sal_False; // sal_True: Drop is enabled
|
|
mpWindowImpl->mbNoUpdate = sal_False; // sal_True: SetUpdateMode( sal_False ) called
|
|
mpWindowImpl->mbNoParentUpdate = sal_False; // sal_True: SetParentUpdateMode( sal_False ) called
|
|
mpWindowImpl->mbActive = sal_False; // sal_True: Window Active
|
|
mpWindowImpl->mbParentActive = sal_False; // sal_True: OverlapActive from Parent
|
|
mpWindowImpl->mbReallyVisible = sal_False; // sal_True: this and all parents to an overlaped window are visible
|
|
mpWindowImpl->mbReallyShown = sal_False; // sal_True: this and all parents to an overlaped window are shown
|
|
mpWindowImpl->mbInInitShow = sal_False; // sal_True: we are in InitShow
|
|
mpWindowImpl->mbChildNotify = sal_False; // sal_True: ChildNotify
|
|
mpWindowImpl->mbChildPtrOverwrite = sal_False; // sal_True: PointerStyle overwrites Child-Pointer
|
|
mpWindowImpl->mbNoPtrVisible = sal_False; // sal_True: ShowPointer( sal_False ) called
|
|
mpWindowImpl->mbMouseMove = sal_False; // sal_True: BaseMouseMove called
|
|
mpWindowImpl->mbPaintFrame = sal_False; // sal_True: Paint is visible, but not painted
|
|
mpWindowImpl->mbInPaint = sal_False; // sal_True: Inside PaintHdl
|
|
mpWindowImpl->mbMouseButtonDown = sal_False; // sal_True: BaseMouseButtonDown called
|
|
mpWindowImpl->mbMouseButtonUp = sal_False; // sal_True: BaseMouseButtonUp called
|
|
mpWindowImpl->mbKeyInput = sal_False; // sal_True: BaseKeyInput called
|
|
mpWindowImpl->mbKeyUp = sal_False; // sal_True: BaseKeyUp called
|
|
mpWindowImpl->mbCommand = sal_False; // sal_True: BaseCommand called
|
|
mpWindowImpl->mbDefPos = sal_True; // sal_True: Position is not Set
|
|
mpWindowImpl->mbDefSize = sal_True; // sal_True: Size is not Set
|
|
mpWindowImpl->mbCallMove = sal_True; // sal_True: Move must be called by Show
|
|
mpWindowImpl->mbCallResize = sal_True; // sal_True: Resize must be called by Show
|
|
mpWindowImpl->mbWaitSystemResize = sal_True; // sal_True: Wait for System-Resize
|
|
mpWindowImpl->mbInitWinClipRegion = sal_True; // sal_True: Calc Window Clip Region
|
|
mpWindowImpl->mbInitChildRegion = sal_False; // sal_True: InitChildClipRegion
|
|
mpWindowImpl->mbWinRegion = sal_False; // sal_True: Window Region
|
|
mpWindowImpl->mbClipChildren = sal_False; // sal_True: Child-window should be clipped
|
|
mpWindowImpl->mbClipSiblings = sal_False; // sal_True: Adjacent Child-window should be clipped
|
|
mpWindowImpl->mbChildTransparent = sal_False; // sal_True: Child-windows are allowed to switch to transparent (incl. Parent-CLIPCHILDREN)
|
|
mpWindowImpl->mbPaintTransparent = sal_False; // sal_True: Paints should be executed on the Parent
|
|
mpWindowImpl->mbMouseTransparent = sal_False; // sal_True: Window is transparent for Mouse
|
|
mpWindowImpl->mbDlgCtrlStart = sal_False; // sal_True: From here on own Dialog-Control
|
|
mpWindowImpl->mbFocusVisible = sal_False; // sal_True: Focus Visible
|
|
mpWindowImpl->mbUseNativeFocus = sal_False;
|
|
mpWindowImpl->mbNativeFocusVisible= sal_False; // sal_True: native Focus Visible
|
|
mpWindowImpl->mbInShowFocus = sal_False; // prevent recursion
|
|
mpWindowImpl->mbInHideFocus = sal_False; // prevent recursion
|
|
mpWindowImpl->mbTrackVisible = sal_False; // sal_True: Tracking Visible
|
|
mpWindowImpl->mbControlForeground = sal_False; // sal_True: Foreground-Property set
|
|
mpWindowImpl->mbControlBackground = sal_False; // sal_True: Background-Property set
|
|
mpWindowImpl->mbAlwaysOnTop = sal_False; // sal_True: always visible for all others windows
|
|
mpWindowImpl->mbCompoundControl = sal_False; // sal_True: Composite Control => Listener...
|
|
mpWindowImpl->mbCompoundControlHasFocus = sal_False; // sal_True: Composite Control has focus somewhere
|
|
mpWindowImpl->mbPaintDisabled = sal_False; // sal_True: Paint should not be executed
|
|
mpWindowImpl->mbAllResize = sal_False; // sal_True: Also sent ResizeEvents with 0,0
|
|
mpWindowImpl->mbInDtor = sal_False; // sal_True: We're still in Window-Dtor
|
|
mpWindowImpl->mbExtTextInput = sal_False; // sal_True: ExtTextInput-Mode is active
|
|
mpWindowImpl->mbInFocusHdl = sal_False; // sal_True: Within GetFocus-Handler
|
|
mpWindowImpl->mbCreatedWithToolkit = sal_False;
|
|
mpWindowImpl->mbSuppressAccessibilityEvents = sal_False; // sal_True: do not send any accessibility events
|
|
mpWindowImpl->mbDrawSelectionBackground = sal_False; // sal_True: draws transparent window background to indicate (toolbox) selection
|
|
mpWindowImpl->mbIsInTaskPaneList = sal_False; // sal_True: window was added to the taskpanelist in the topmost system window
|
|
mpWindowImpl->mnNativeBackground = 0; // initialize later, depends on type
|
|
mpWindowImpl->mbCallHandlersDuringInputDisabled = sal_False; // sal_True: call event handlers even if input is disabled
|
|
mpWindowImpl->mbHelpTextDynamic = sal_False; // sal_True: append help id in HELP_DEBUG case
|
|
mpWindowImpl->mbFakeFocusSet = sal_False; // sal_True: pretend as if the window has focus.
|
|
mpWindowImpl->mbHexpand = false;
|
|
mpWindowImpl->mbVexpand = false;
|
|
mpWindowImpl->mbExpand = false;
|
|
mpWindowImpl->mbFill = true;
|
|
mpWindowImpl->mbSecondary = false;
|
|
|
|
|
|
mbEnableRTL = Application::GetSettings().GetLayoutRTL(); // sal_True: this outdev will be mirrored if RTL window layout (UI mirroring) is globally active
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplInit( Window* pParent, WinBits nStyle, SystemParentData* pSystemParentData )
|
|
{
|
|
DBG_ASSERT( mpWindowImpl->mbFrame || pParent, "Window::Window(): pParent == NULL" );
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
Window* pRealParent = pParent;
|
|
|
|
// 3D-Look vererben
|
|
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) ) )
|
|
{
|
|
sal_uInt16 nBorderTypeStyle = 0;
|
|
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 BORDERWINDOW_STYLE_FRAME
|
|
// which controls their size
|
|
nBorderTypeStyle |= BORDERWINDOW_STYLE_FRAME;
|
|
nStyle |= WB_BORDER;
|
|
}
|
|
ImplBorderWindow* pBorderWin = new ImplBorderWindow( pParent, nStyle & (WB_BORDER | WB_DIALOGCONTROL | WB_NODIALOGCONTROL | WB_NEEDSFOCUS), nBorderTypeStyle );
|
|
((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 = sal_True;
|
|
mpWindowImpl->mbFrame = sal_True;
|
|
}
|
|
|
|
// insert window in list
|
|
ImplInsertWindow( pParent );
|
|
mpWindowImpl->mnStyle = nStyle;
|
|
|
|
// Overlap-Window-Data
|
|
if ( mpWindowImpl->mbOverlapWin )
|
|
{
|
|
mpWindowImpl->mpOverlapData = new ImplOverlapData;
|
|
mpWindowImpl->mpOverlapData->mpSaveBackDev = NULL;
|
|
mpWindowImpl->mpOverlapData->mpSaveBackRgn = NULL;
|
|
mpWindowImpl->mpOverlapData->mpNextBackWin = NULL;
|
|
mpWindowImpl->mpOverlapData->mnSaveBackSize = 0;
|
|
mpWindowImpl->mpOverlapData->mbSaveBack = sal_False;
|
|
mpWindowImpl->mpOverlapData->mnTopLevel = 1;
|
|
}
|
|
|
|
if( pParent && ! mpWindowImpl->mbFrame )
|
|
mbEnableRTL = Application::GetSettings().GetLayoutRTL();
|
|
|
|
// test for frame creation
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
// create frame
|
|
sal_uLong nFrameStyle = 0;
|
|
|
|
if ( nStyle & WB_MOVEABLE )
|
|
nFrameStyle |= SAL_FRAME_STYLE_MOVEABLE;
|
|
if ( nStyle & WB_SIZEABLE )
|
|
nFrameStyle |= SAL_FRAME_STYLE_SIZEABLE;
|
|
if ( nStyle & WB_CLOSEABLE )
|
|
nFrameStyle |= SAL_FRAME_STYLE_CLOSEABLE;
|
|
if ( nStyle & WB_APP )
|
|
nFrameStyle |= SAL_FRAME_STYLE_DEFAULT;
|
|
// check for undecorated floating window
|
|
if( // 1. floating windows that are not moveable/sizeable (only closeable allowed)
|
|
( !(nFrameStyle & ~SAL_FRAME_STYLE_CLOSEABLE) &&
|
|
( mpWindowImpl->mbFloatWin || ((GetType() == WINDOW_BORDERWINDOW) && ((ImplBorderWindow*)this)->mbFloatWindow) || (nStyle & WB_SYSTEMFLOATWIN) ) ) ||
|
|
// 2. borderwindows of floaters with ownerdraw decoration
|
|
( ((GetType() == WINDOW_BORDERWINDOW) && ((ImplBorderWindow*)this)->mbFloatWindow && (nStyle & WB_OWNERDRAWDECORATION) ) ) )
|
|
{
|
|
nFrameStyle = SAL_FRAME_STYLE_FLOAT;
|
|
if( nStyle & WB_OWNERDRAWDECORATION )
|
|
nFrameStyle |= (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_NOSHADOW);
|
|
if( nStyle & WB_NEEDSFOCUS )
|
|
nFrameStyle |= SAL_FRAME_STYLE_FLOAT_FOCUSABLE;
|
|
}
|
|
else if( mpWindowImpl->mbFloatWin )
|
|
nFrameStyle |= SAL_FRAME_STYLE_TOOLWINDOW;
|
|
|
|
if( nStyle & WB_INTROWIN )
|
|
nFrameStyle |= SAL_FRAME_STYLE_INTRO;
|
|
if( nStyle & WB_TOOLTIPWIN )
|
|
nFrameStyle |= SAL_FRAME_STYLE_TOOLTIP;
|
|
|
|
if( nStyle & WB_NOSHADOW )
|
|
nFrameStyle |= SAL_FRAME_STYLE_NOSHADOW;
|
|
|
|
if( nStyle & WB_SYSTEMCHILDWINDOW )
|
|
nFrameStyle |= SAL_FRAME_STYLE_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 |= SAL_FRAME_STYLE_DIALOG;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
SalFrame* pParentFrame = NULL;
|
|
if ( pParent )
|
|
pParentFrame = pParent->mpWindowImpl->mpFrame;
|
|
SalFrame* pFrame;
|
|
if ( pSystemParentData )
|
|
pFrame = pSVData->mpDefInst->CreateChildFrame( pSystemParentData, nFrameStyle | SAL_FRAME_STYLE_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 ::com::sun::star::uno::RuntimeException(
|
|
OUString( "Could not create system window!" ),
|
|
::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
|
|
//GetpApp()->Exception( EXC_SYSOBJNOTCREATED );
|
|
}
|
|
|
|
pFrame->SetCallback( this, ImplWindowFrameProc );
|
|
|
|
// set window frame data
|
|
mpWindowImpl->mpFrameData = new ImplFrameData;
|
|
mpWindowImpl->mpFrame = pFrame;
|
|
mpWindowImpl->mpFrameWindow = this;
|
|
mpWindowImpl->mpOverlapWindow = this;
|
|
|
|
// set frame data
|
|
mpWindowImpl->mpFrameData->mpNextFrame = pSVData->maWinData.mpFirstFrame;
|
|
pSVData->maWinData.mpFirstFrame = this;
|
|
mpWindowImpl->mpFrameData->mpFirstOverlap = NULL;
|
|
mpWindowImpl->mpFrameData->mpFocusWin = NULL;
|
|
mpWindowImpl->mpFrameData->mpMouseMoveWin = NULL;
|
|
mpWindowImpl->mpFrameData->mpMouseDownWin = NULL;
|
|
mpWindowImpl->mpFrameData->mpFirstBackWin = NULL;
|
|
mpWindowImpl->mpFrameData->mpFontList = pSVData->maGDIData.mpScreenFontList;
|
|
mpWindowImpl->mpFrameData->mpFontCache = pSVData->maGDIData.mpScreenFontCache;
|
|
mpWindowImpl->mpFrameData->mnAllSaveBackSize = 0;
|
|
mpWindowImpl->mpFrameData->mnFocusId = 0;
|
|
mpWindowImpl->mpFrameData->mnMouseMoveId = 0;
|
|
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 = 0;
|
|
mpWindowImpl->mpFrameData->meMapUnit = MAP_PIXEL;
|
|
mpWindowImpl->mpFrameData->mbHasFocus = sal_False;
|
|
mpWindowImpl->mpFrameData->mbInMouseMove = sal_False;
|
|
mpWindowImpl->mpFrameData->mbMouseIn = sal_False;
|
|
mpWindowImpl->mpFrameData->mbStartDragCalled = sal_False;
|
|
mpWindowImpl->mpFrameData->mbNeedSysWindow = sal_False;
|
|
mpWindowImpl->mpFrameData->mbMinimized = sal_False;
|
|
mpWindowImpl->mpFrameData->mbStartFocusState = sal_False;
|
|
mpWindowImpl->mpFrameData->mbInSysObjFocusHdl = sal_False;
|
|
mpWindowImpl->mpFrameData->mbInSysObjToTopHdl = sal_False;
|
|
mpWindowImpl->mpFrameData->mbSysObjFocus = sal_False;
|
|
mpWindowImpl->mpFrameData->maPaintTimer.SetTimeout( 30 );
|
|
mpWindowImpl->mpFrameData->maPaintTimer.SetTimeoutHdl( LINK( this, Window, ImplHandlePaintHdl ) );
|
|
mpWindowImpl->mpFrameData->maResizeTimer.SetTimeout( 50 );
|
|
mpWindowImpl->mpFrameData->maResizeTimer.SetTimeoutHdl( LINK( this, Window, ImplHandleResizeTimerHdl ) );
|
|
mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = sal_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
|
|
mpFontList = mpWindowImpl->mpFrameData->mpFontList;
|
|
mpFontCache = mpWindowImpl->mpFrameData->mpFontCache;
|
|
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
if ( pParent )
|
|
{
|
|
mpWindowImpl->mpFrameData->mnDPIX = pParent->mpWindowImpl->mpFrameData->mnDPIX;
|
|
mpWindowImpl->mpFrameData->mnDPIY = pParent->mpWindowImpl->mpFrameData->mnDPIY;
|
|
}
|
|
else
|
|
{
|
|
if ( ImplGetGraphics() )
|
|
{
|
|
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 = sal_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;
|
|
}
|
|
|
|
OutputDevice::SetSettings( pParent->GetSettings() );
|
|
}
|
|
|
|
}
|
|
|
|
const StyleSettings& rStyleSettings = maSettings.GetStyleSettings();
|
|
sal_uInt16 nScreenZoom = rStyleSettings.GetScreenZoom();
|
|
mnDPIX = (mpWindowImpl->mpFrameData->mnDPIX*nScreenZoom)/100;
|
|
mnDPIY = (mpWindowImpl->mpFrameData->mnDPIY*nScreenZoom)/100;
|
|
maFont = rStyleSettings.GetAppFont();
|
|
ImplPointToLogic( maFont );
|
|
|
|
if ( nStyle & WB_3DLOOK )
|
|
{
|
|
SetTextColor( rStyleSettings.GetButtonTextColor() );
|
|
SetBackground( Wallpaper( rStyleSettings.GetFaceColor() ) );
|
|
}
|
|
else
|
|
{
|
|
SetTextColor( rStyleSettings.GetWindowTextColor() );
|
|
SetBackground( Wallpaper( rStyleSettings.GetWindowColor() ) );
|
|
}
|
|
|
|
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()->ImplCallEventListeners( VCLEVENT_WINDOW_CHILDCREATED, this );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplSetFrameParent( const Window* pParent )
|
|
{
|
|
Window* pFrameWindow = ImplGetSVData()->maWinData.mpFirstFrame;
|
|
while( pFrameWindow )
|
|
{
|
|
// search all frames that are children of this window
|
|
// and reparent them
|
|
if( ImplIsRealParentPath( pFrameWindow ) )
|
|
{
|
|
DBG_ASSERT( mpWindowImpl->mpFrame != pFrameWindow->mpWindowImpl->mpFrame, "SetFrameParent to own" );
|
|
DBG_ASSERT( mpWindowImpl->mpFrame, "no frame" );
|
|
SalFrame* pParentFrame = pParent ? pParent->mpWindowImpl->mpFrame : NULL;
|
|
pFrameWindow->mpWindowImpl->mpFrame->SetParent( pParentFrame );
|
|
}
|
|
pFrameWindow = pFrameWindow->mpWindowImpl->mpFrameData->mpNextFrame;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplInsertWindow( Window* pParent )
|
|
{
|
|
mpWindowImpl->mpParent = pParent;
|
|
mpWindowImpl->mpRealParent = pParent;
|
|
|
|
if ( pParent && !mpWindowImpl->mbFrame )
|
|
{
|
|
// search frame window and set window frame data
|
|
Window* pFrameParent = pParent->mpWindowImpl->mpFrameWindow;
|
|
mpWindowImpl->mpFrameData = pFrameParent->mpWindowImpl->mpFrameData;
|
|
mpWindowImpl->mpFrame = pFrameParent->mpWindowImpl->mpFrame;
|
|
mpWindowImpl->mpFrameWindow = pFrameParent;
|
|
mpWindowImpl->mbFrame = sal_False;
|
|
|
|
// search overlap window and insert window in list
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
Window* pFirstOverlapParent = pParent;
|
|
while ( !pFirstOverlapParent->ImplIsOverlapWindow() )
|
|
pFirstOverlapParent = pFirstOverlapParent->ImplGetParent();
|
|
mpWindowImpl->mpOverlapWindow = pFirstOverlapParent;
|
|
|
|
mpWindowImpl->mpNextOverlap = mpWindowImpl->mpFrameData->mpFirstOverlap;
|
|
mpWindowImpl->mpFrameData->mpFirstOverlap = this;
|
|
|
|
// Overlap-Windows are by default the uppermost
|
|
mpWindowImpl->mpNext = pFirstOverlapParent->mpWindowImpl->mpFirstOverlap;
|
|
pFirstOverlapParent->mpWindowImpl->mpFirstOverlap = this;
|
|
if ( !pFirstOverlapParent->mpWindowImpl->mpLastOverlap )
|
|
pFirstOverlapParent->mpWindowImpl->mpLastOverlap = this;
|
|
else
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = this;
|
|
}
|
|
else
|
|
{
|
|
if ( pParent->ImplIsOverlapWindow() )
|
|
mpWindowImpl->mpOverlapWindow = pParent;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow = pParent->mpWindowImpl->mpOverlapWindow;
|
|
mpWindowImpl->mpPrev = pParent->mpWindowImpl->mpLastChild;
|
|
pParent->mpWindowImpl->mpLastChild = this;
|
|
if ( !pParent->mpWindowImpl->mpFirstChild )
|
|
pParent->mpWindowImpl->mpFirstChild = this;
|
|
else
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplRemoveWindow( sal_Bool bRemoveFrameData )
|
|
{
|
|
// remove window from the lists
|
|
if ( !mpWindowImpl->mbFrame )
|
|
{
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
if ( mpWindowImpl->mpFrameData->mpFirstOverlap == this )
|
|
mpWindowImpl->mpFrameData->mpFirstOverlap = mpWindowImpl->mpNextOverlap;
|
|
else
|
|
{
|
|
Window* pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap;
|
|
while ( pTempWin->mpWindowImpl->mpNextOverlap != this )
|
|
pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
|
|
pTempWin->mpWindowImpl->mpNextOverlap = mpWindowImpl->mpNextOverlap;
|
|
}
|
|
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
|
|
}
|
|
else
|
|
{
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else if ( mpWindowImpl->mpParent )
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else if ( mpWindowImpl->mpParent )
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = mpWindowImpl->mpPrev;
|
|
}
|
|
|
|
mpWindowImpl->mpPrev = NULL;
|
|
mpWindowImpl->mpNext = NULL;
|
|
}
|
|
|
|
if ( bRemoveFrameData )
|
|
{
|
|
// release the graphic
|
|
ImplReleaseGraphics();
|
|
}
|
|
}
|
|
|
|
void Window::reorderWithinParent(sal_uInt16 nNewPosition)
|
|
{
|
|
sal_uInt16 nChildCount = 0;
|
|
Window *pSource = mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild;
|
|
while (pSource)
|
|
{
|
|
if (nChildCount == nNewPosition)
|
|
break;
|
|
pSource = pSource->mpWindowImpl->mpNext;
|
|
nChildCount++;
|
|
}
|
|
|
|
if (pSource == this) //already at the right place
|
|
return;
|
|
|
|
ImplRemoveWindow(false);
|
|
|
|
if (pSource)
|
|
{
|
|
mpWindowImpl->mpNext = pSource;
|
|
mpWindowImpl->mpPrev = pSource->mpWindowImpl->mpPrev;
|
|
pSource->mpWindowImpl->mpPrev = this;
|
|
}
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = this;
|
|
|
|
if (mpWindowImpl->mpPrev)
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = this;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCallResize()
|
|
{
|
|
mpWindowImpl->mbCallResize = sal_False;
|
|
|
|
if( GetBackground().IsGradient() )
|
|
Invalidate();
|
|
|
|
Resize();
|
|
|
|
// #88419# Most classes don't call the base class in Resize() and Move(),
|
|
// => Call ImpleResize/Move instead of Resize/Move directly...
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_RESIZE );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCallMove()
|
|
{
|
|
mpWindowImpl->mbCallMove = sal_False;
|
|
|
|
if( mpWindowImpl->mbFrame )
|
|
{
|
|
// update frame position
|
|
SalFrame *pParentFrame = NULL;
|
|
Window *pParent = ImplGetParent();
|
|
while( pParent )
|
|
{
|
|
if( pParent->mpWindowImpl->mpFrame != mpWindowImpl->mpFrame )
|
|
{
|
|
pParentFrame = pParent->mpWindowImpl->mpFrame;
|
|
break;
|
|
}
|
|
pParent = pParent->GetParent();
|
|
}
|
|
|
|
SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
|
|
mpWindowImpl->maPos = Point( g.nX, g.nY );
|
|
if( pParentFrame )
|
|
{
|
|
g = pParentFrame->GetGeometry();
|
|
mpWindowImpl->maPos -= Point( g.nX, g.nY );
|
|
}
|
|
// the client window and and all its subclients have the same position as the borderframe
|
|
// this is important for floating toolbars where the borderwindow is a floating window
|
|
// which has another borderwindow (ie the system floating window)
|
|
Window *pClientWin = mpWindowImpl->mpClientWindow;
|
|
while( pClientWin )
|
|
{
|
|
pClientWin->mpWindowImpl->maPos = mpWindowImpl->maPos;
|
|
pClientWin = pClientWin->mpWindowImpl->mpClientWindow;
|
|
}
|
|
}
|
|
|
|
Move();
|
|
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_MOVE );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
static rtl::OString ImplAutoHelpID( ResMgr* pResMgr )
|
|
{
|
|
rtl::OString aRet;
|
|
|
|
if( pResMgr && Application::IsAutoHelpIdEnabled() )
|
|
aRet = pResMgr->GetAutoHelpId();
|
|
|
|
return aRet;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
WinBits Window::ImplInitRes( const ResId& rResId )
|
|
{
|
|
GetRes( rResId );
|
|
|
|
char* pRes = (char*)GetClassRes();
|
|
pRes += 8;
|
|
sal_uInt32 nStyle = (sal_uInt32)GetLongRes( (void*)pRes );
|
|
rResId.SetWinBits( nStyle );
|
|
return nStyle;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
WindowResHeader Window::ImplLoadResHeader( const ResId& rResId )
|
|
{
|
|
WindowResHeader aHeader;
|
|
|
|
aHeader.nObjMask = ReadLongRes();
|
|
|
|
// we need to calculate auto helpids before the resource gets closed
|
|
// if the resource only contains flags, it will be closed before we try to read a help id
|
|
// so we always create an auto help id that might be overwritten later
|
|
// HelpId
|
|
aHeader.aHelpId = ImplAutoHelpID( rResId.GetResMgr() );
|
|
|
|
// ResourceStyle
|
|
aHeader.nRSStyle = ReadLongRes();
|
|
// WinBits
|
|
ReadLongRes();
|
|
|
|
if( aHeader.nObjMask & WINDOW_HELPID )
|
|
aHeader.aHelpId = ReadByteStringRes();
|
|
|
|
return aHeader;
|
|
}
|
|
|
|
void Window::ImplLoadRes( const ResId& rResId )
|
|
{
|
|
WindowResHeader aHeader = ImplLoadResHeader( rResId );
|
|
|
|
SetHelpId( aHeader.aHelpId );
|
|
|
|
sal_uLong nObjMask = aHeader.nObjMask;
|
|
|
|
sal_Bool bPos = sal_False;
|
|
sal_Bool bSize = sal_False;
|
|
Point aPos;
|
|
Size aSize;
|
|
|
|
if ( nObjMask & (WINDOW_XYMAPMODE | WINDOW_X | WINDOW_Y) )
|
|
{
|
|
// use size as per resource
|
|
MapUnit ePosMap = MAP_PIXEL;
|
|
|
|
bPos = sal_True;
|
|
|
|
if ( nObjMask & WINDOW_XYMAPMODE )
|
|
ePosMap = (MapUnit)ReadLongRes();
|
|
if ( nObjMask & WINDOW_X )
|
|
aPos.X() = ImplLogicUnitToPixelX( ReadLongRes(), ePosMap );
|
|
if ( nObjMask & WINDOW_Y )
|
|
aPos.Y() = ImplLogicUnitToPixelY( ReadLongRes(), ePosMap );
|
|
}
|
|
|
|
if ( nObjMask & (WINDOW_WHMAPMODE | WINDOW_WIDTH | WINDOW_HEIGHT) )
|
|
{
|
|
// use size as per resource
|
|
MapUnit eSizeMap = MAP_PIXEL;
|
|
|
|
bSize = sal_True;
|
|
|
|
if ( nObjMask & WINDOW_WHMAPMODE )
|
|
eSizeMap = (MapUnit)ReadLongRes();
|
|
if ( nObjMask & WINDOW_WIDTH )
|
|
aSize.Width() = ImplLogicUnitToPixelX( ReadLongRes(), eSizeMap );
|
|
if ( nObjMask & WINDOW_HEIGHT )
|
|
aSize.Height() = ImplLogicUnitToPixelY( ReadLongRes(), eSizeMap );
|
|
}
|
|
|
|
sal_uLong nRSStyle = aHeader.nRSStyle;
|
|
|
|
// looks bad due to optimisation
|
|
if ( nRSStyle & RSWND_CLIENTSIZE )
|
|
{
|
|
if ( bPos )
|
|
SetPosPixel( aPos );
|
|
if ( bSize )
|
|
SetOutputSizePixel( aSize );
|
|
}
|
|
else if ( bPos && bSize )
|
|
SetPosSizePixel( aPos, aSize );
|
|
else if ( bPos )
|
|
SetPosPixel( aPos );
|
|
else if ( bSize )
|
|
SetSizePixel( aSize );
|
|
|
|
if ( nRSStyle & RSWND_DISABLED )
|
|
Enable( sal_False );
|
|
|
|
if ( nObjMask & WINDOW_TEXT )
|
|
SetText( ReadStringRes() );
|
|
if ( nObjMask & WINDOW_HELPTEXT )
|
|
{
|
|
SetHelpText( ReadStringRes() );
|
|
mpWindowImpl->mbHelpTextDynamic = sal_True;
|
|
}
|
|
if ( nObjMask & WINDOW_QUICKTEXT )
|
|
SetQuickHelpText( ReadStringRes() );
|
|
if ( nObjMask & WINDOW_EXTRALONG )
|
|
{
|
|
sal_uIntPtr nRes = ReadLongRes();
|
|
SetData( (void*)nRes );
|
|
}
|
|
if ( nObjMask & WINDOW_UNIQUEID )
|
|
SetUniqueId( ReadByteStringRes() );
|
|
|
|
if ( nObjMask & WINDOW_BORDER_STYLE )
|
|
{
|
|
sal_uInt16 nBorderStyle = (sal_uInt16)ReadLongRes();
|
|
SetBorderStyle( nBorderStyle );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
ImplWinData* Window::ImplGetWinData() const
|
|
{
|
|
if ( !mpWindowImpl->mpWinData )
|
|
{
|
|
static const char* pNoNWF = getenv( "SAL_NO_NWF" );
|
|
|
|
((Window*)this)->mpWindowImpl->mpWinData = new ImplWinData;
|
|
mpWindowImpl->mpWinData->mpExtOldText = NULL;
|
|
mpWindowImpl->mpWinData->mpExtOldAttrAry = NULL;
|
|
mpWindowImpl->mpWinData->mpCursorRect = 0;
|
|
mpWindowImpl->mpWinData->mnCursorExtWidth = 0;
|
|
mpWindowImpl->mpWinData->mpFocusRect = NULL;
|
|
mpWindowImpl->mpWinData->mpTrackRect = NULL;
|
|
mpWindowImpl->mpWinData->mnTrackFlags = 0;
|
|
mpWindowImpl->mpWinData->mnIsTopWindow = (sal_uInt16) ~0; // not initialized yet, 0/1 will indicate TopWindow (see IsTopWindow())
|
|
mpWindowImpl->mpWinData->mbMouseOver = sal_False;
|
|
mpWindowImpl->mpWinData->mbEnableNativeWidget = (pNoNWF && *pNoNWF) ? sal_False : sal_True; // sal_True: try to draw this control with native theme API
|
|
}
|
|
|
|
return mpWindowImpl->mpWinData;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
SalGraphics* Window::ImplGetFrameGraphics() const
|
|
{
|
|
if ( mpWindowImpl->mpFrameWindow->mpGraphics )
|
|
mpWindowImpl->mpFrameWindow->mbInitClipRegion = sal_True;
|
|
else
|
|
mpWindowImpl->mpFrameWindow->ImplGetGraphics();
|
|
mpWindowImpl->mpFrameWindow->mpGraphics->ResetClipRegion();
|
|
return mpWindowImpl->mpFrameWindow->mpGraphics;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Window* Window::ImplFindWindow( const Point& rFramePos )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
Window* pTempWindow;
|
|
Window* pFindWindow;
|
|
|
|
// first check all overlapping windows
|
|
pTempWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pTempWindow )
|
|
{
|
|
pFindWindow = pTempWindow->ImplFindWindow( rFramePos );
|
|
if ( pFindWindow )
|
|
return pFindWindow;
|
|
pTempWindow = pTempWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
// then we check our window
|
|
if ( !mpWindowImpl->mbVisible )
|
|
return NULL;
|
|
|
|
sal_uInt16 nHitTest = ImplHitTest( rFramePos );
|
|
if ( nHitTest & WINDOW_HITTEST_INSIDE )
|
|
{
|
|
// and then we check all child windows
|
|
pTempWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pTempWindow )
|
|
{
|
|
pFindWindow = pTempWindow->ImplFindWindow( rFramePos );
|
|
if ( pFindWindow )
|
|
return pFindWindow;
|
|
pTempWindow = pTempWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
if ( nHitTest & WINDOW_HITTEST_TRANSPARENT )
|
|
return NULL;
|
|
else
|
|
return this;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_uInt16 Window::ImplHitTest( const Point& rFramePos )
|
|
{
|
|
Point aFramePos( rFramePos );
|
|
if( ImplIsAntiparallel() )
|
|
{
|
|
// - RTL - re-mirror frame pos at this window
|
|
ImplReMirror( aFramePos );
|
|
}
|
|
Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
if ( !aRect.IsInside( aFramePos ) )
|
|
return 0;
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
{
|
|
Point aTempPos = aFramePos;
|
|
aTempPos.X() -= mnOutOffX;
|
|
aTempPos.Y() -= mnOutOffY;
|
|
if ( !mpWindowImpl->maWinRegion.IsInside( aTempPos ) )
|
|
return 0;
|
|
}
|
|
|
|
sal_uInt16 nHitTest = WINDOW_HITTEST_INSIDE;
|
|
if ( mpWindowImpl->mbMouseTransparent )
|
|
nHitTest |= WINDOW_HITTEST_TRANSPARENT;
|
|
return nHitTest;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::ImplIsRealParentPath( const Window* pWindow ) const
|
|
{
|
|
pWindow = pWindow->GetParent();
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow == this )
|
|
return sal_True;
|
|
pWindow = pWindow->GetParent();
|
|
}
|
|
|
|
return sal_False;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::ImplIsChild( const Window* pWindow, sal_Bool bSystemWindow ) const
|
|
{
|
|
do
|
|
{
|
|
if ( !bSystemWindow && pWindow->ImplIsOverlapWindow() )
|
|
break;
|
|
|
|
pWindow = pWindow->ImplGetParent();
|
|
|
|
if ( pWindow == this )
|
|
return sal_True;
|
|
}
|
|
while ( pWindow );
|
|
|
|
return sal_False;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::ImplIsWindowOrChild( const Window* pWindow, sal_Bool bSystemWindow ) const
|
|
{
|
|
if ( this == pWindow )
|
|
return sal_True;
|
|
return ImplIsChild( pWindow, bSystemWindow );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
int Window::ImplTestMousePointerSet()
|
|
{
|
|
// as soon as mouse is captured, switch mouse-pointer
|
|
if ( IsMouseCaptured() )
|
|
return sal_True;
|
|
|
|
// if the mouse is over the window, switch it
|
|
Rectangle aClientRect( Point( 0, 0 ), GetOutputSizePixel() );
|
|
if ( aClientRect.IsInside( GetPointerPosPixel() ) )
|
|
return sal_True;
|
|
|
|
return sal_False;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
PointerStyle Window::ImplGetMousePointer() const
|
|
{
|
|
PointerStyle ePointerStyle;
|
|
sal_Bool bWait = sal_False;
|
|
|
|
if ( IsEnabled() && IsInputEnabled() && ! IsInModalMode() )
|
|
ePointerStyle = GetPointer().GetStyle();
|
|
else
|
|
ePointerStyle = POINTER_ARROW;
|
|
|
|
const Window* pWindow = this;
|
|
do
|
|
{
|
|
// when the pointer is not visible stop the search, as
|
|
// this status should not be overwritten
|
|
if ( pWindow->mpWindowImpl->mbNoPtrVisible )
|
|
return POINTER_NULL;
|
|
|
|
if ( !bWait )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mnWaitCount )
|
|
{
|
|
ePointerStyle = POINTER_WAIT;
|
|
bWait = sal_True;
|
|
}
|
|
else
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbChildPtrOverwrite )
|
|
ePointerStyle = pWindow->GetPointer().GetStyle();
|
|
}
|
|
}
|
|
|
|
if ( pWindow->ImplIsOverlapWindow() )
|
|
break;
|
|
|
|
pWindow = pWindow->ImplGetParent();
|
|
}
|
|
while ( pWindow );
|
|
|
|
return ePointerStyle;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplResetReallyVisible()
|
|
{
|
|
sal_Bool bBecameReallyInvisible = mpWindowImpl->mbReallyVisible;
|
|
|
|
mbDevOutput = sal_False;
|
|
mpWindowImpl->mbReallyVisible = sal_False;
|
|
mpWindowImpl->mbReallyShown = sal_False;
|
|
|
|
// the SHOW/HIDE events serve as indicators to send child creation/destroy events to the access bridge.
|
|
// For this, the data member of the event must not be NULL.
|
|
// Previously, we did this in Window::Show, but there some events got lost in certain situations.
|
|
if( bBecameReallyInvisible && ImplIsAccessibleCandidate() )
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_HIDE, this );
|
|
// TODO. It's kind of a hack that we're re-using the VCLEVENT_WINDOW_HIDE. Normally, we should
|
|
// introduce another event which explicitly triggers the Accessibility implementations.
|
|
|
|
Window* pWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible )
|
|
pWindow->ImplResetReallyVisible();
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible )
|
|
pWindow->ImplResetReallyVisible();
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::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();
|
|
|
|
sal_Bool bBecameReallyVisible = !mpWindowImpl->mbReallyVisible;
|
|
|
|
mbDevOutput = sal_True;
|
|
mpWindowImpl->mbReallyVisible = sal_True;
|
|
mpWindowImpl->mbReallyShown = sal_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() )
|
|
ImplCallEventListeners( 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.
|
|
|
|
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::ImplCallInitShow()
|
|
{
|
|
mpWindowImpl->mbReallyShown = sal_True;
|
|
mpWindowImpl->mbInInitShow = sal_True;
|
|
StateChanged( STATE_CHANGE_INITSHOW );
|
|
mpWindowImpl->mbInInitShow = sal_False;
|
|
|
|
Window* pWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbVisible )
|
|
pWindow->ImplCallInitShow();
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbVisible )
|
|
pWindow->ImplCallInitShow();
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplAddDel( ImplDelData* pDel ) // TODO: make "const" when incompatiblity ok
|
|
{
|
|
DBG_ASSERT( !pDel->mpWindow, "Window::ImplAddDel(): cannot add ImplDelData twice !" );
|
|
if( !pDel->mpWindow )
|
|
{
|
|
pDel->mpWindow = this; // #112873# store ref to this window, so pDel can remove itself
|
|
pDel->mpNext = mpWindowImpl->mpFirstDel;
|
|
mpWindowImpl->mpFirstDel = pDel;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplRemoveDel( ImplDelData* pDel ) // TODO: make "const" when incompatiblity ok
|
|
{
|
|
pDel->mpWindow = NULL; // #112873# pDel is not associated with a Window anymore
|
|
if ( mpWindowImpl->mpFirstDel == pDel )
|
|
mpWindowImpl->mpFirstDel = pDel->mpNext;
|
|
else
|
|
{
|
|
ImplDelData* pData = mpWindowImpl->mpFirstDel;
|
|
while ( pData->mpNext != pDel )
|
|
pData = pData->mpNext;
|
|
pData->mpNext = pDel->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplInitResolutionSettings()
|
|
{
|
|
// recalculate AppFont-resolution and DPI-resolution
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
const StyleSettings& rStyleSettings = maSettings.GetStyleSettings();
|
|
sal_uInt16 nScreenZoom = rStyleSettings.GetScreenZoom();
|
|
mnDPIX = (mpWindowImpl->mpFrameData->mnDPIX*nScreenZoom)/100;
|
|
mnDPIY = (mpWindowImpl->mpFrameData->mnDPIY*nScreenZoom)/100;
|
|
SetPointFont( rStyleSettings.GetAppFont() );
|
|
}
|
|
else if ( mpWindowImpl->mpParent )
|
|
{
|
|
mnDPIX = mpWindowImpl->mpParent->mnDPIX;
|
|
mnDPIY = mpWindowImpl->mpParent->mnDPIY;
|
|
}
|
|
|
|
// update the recalculated values for logical units
|
|
// and also tools belonging to the values
|
|
if ( IsMapMode() )
|
|
{
|
|
MapMode aMapMode = GetMapMode();
|
|
SetMapMode();
|
|
SetMapMode( aMapMode );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplPointToLogic( Font& rFont ) const
|
|
{
|
|
Size aSize = rFont.GetSize();
|
|
sal_uInt16 nScreenFontZoom = maSettings.GetStyleSettings().GetScreenFontZoom();
|
|
|
|
if ( aSize.Width() )
|
|
{
|
|
aSize.Width() *= mpWindowImpl->mpFrameData->mnDPIX;
|
|
aSize.Width() += 72/2;
|
|
aSize.Width() /= 72;
|
|
aSize.Width() *= nScreenFontZoom;
|
|
aSize.Width() /= 100;
|
|
}
|
|
aSize.Height() *= mpWindowImpl->mpFrameData->mnDPIY;
|
|
aSize.Height() += 72/2;
|
|
aSize.Height() /= 72;
|
|
aSize.Height() *= nScreenFontZoom;
|
|
aSize.Height() /= 100;
|
|
|
|
if ( IsMapModeEnabled() )
|
|
aSize = PixelToLogic( aSize );
|
|
|
|
rFont.SetSize( aSize );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplLogicToPoint( Font& rFont ) const
|
|
{
|
|
Size aSize = rFont.GetSize();
|
|
sal_uInt16 nScreenFontZoom = maSettings.GetStyleSettings().GetScreenFontZoom();
|
|
|
|
if ( IsMapModeEnabled() )
|
|
aSize = LogicToPixel( aSize );
|
|
|
|
if ( aSize.Width() )
|
|
{
|
|
aSize.Width() *= 100;
|
|
aSize.Width() /= nScreenFontZoom;
|
|
aSize.Width() *= 72;
|
|
aSize.Width() += mpWindowImpl->mpFrameData->mnDPIX/2;
|
|
aSize.Width() /= mpWindowImpl->mpFrameData->mnDPIX;
|
|
}
|
|
aSize.Height() *= 100;
|
|
aSize.Height() /= nScreenFontZoom;
|
|
aSize.Height() *= 72;
|
|
aSize.Height() += mpWindowImpl->mpFrameData->mnDPIY/2;
|
|
aSize.Height() /= mpWindowImpl->mpFrameData->mnDPIY;
|
|
|
|
rFont.SetSize( aSize );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::ImplSysObjClip( const Region* pOldRegion )
|
|
{
|
|
sal_Bool bUpdate = sal_True;
|
|
|
|
if ( mpWindowImpl->mpSysObj )
|
|
{
|
|
bool bVisibleState = mpWindowImpl->mbReallyVisible;
|
|
|
|
if ( bVisibleState )
|
|
{
|
|
Region* pWinChildClipRegion = ImplGetWinChildClipRegion();
|
|
|
|
if ( !pWinChildClipRegion->IsEmpty() )
|
|
{
|
|
if ( pOldRegion )
|
|
{
|
|
Region aNewRegion = *pWinChildClipRegion;
|
|
pWinChildClipRegion->Intersect( *pOldRegion );
|
|
bUpdate = aNewRegion == *pWinChildClipRegion;
|
|
}
|
|
|
|
if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
|
|
ImplInvalidateAllOverlapBackgrounds();
|
|
|
|
Region aRegion = *pWinChildClipRegion;
|
|
Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
Region aWinRectRegion( aWinRect );
|
|
sal_uInt16 nClipFlags = mpWindowImpl->mpSysObj->GetClipRegionType();
|
|
|
|
if ( aRegion == aWinRectRegion )
|
|
mpWindowImpl->mpSysObj->ResetClipRegion();
|
|
else
|
|
{
|
|
if ( nClipFlags & SAL_OBJECT_CLIP_EXCLUDERECTS )
|
|
{
|
|
aWinRectRegion.Exclude( aRegion );
|
|
aRegion = aWinRectRegion;
|
|
}
|
|
if ( !(nClipFlags & SAL_OBJECT_CLIP_ABSOLUTE) )
|
|
aRegion.Move( -mnOutOffX, -mnOutOffY );
|
|
|
|
// ClipRegion setzen/updaten
|
|
long nX;
|
|
long nY;
|
|
long nWidth;
|
|
long nHeight;
|
|
sal_uLong nRectCount;
|
|
ImplRegionInfo aInfo;
|
|
sal_Bool bRegionRect;
|
|
|
|
nRectCount = aRegion.GetRectCount();
|
|
mpWindowImpl->mpSysObj->BeginSetClipRegion( nRectCount );
|
|
bRegionRect = aRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
|
|
while ( bRegionRect )
|
|
{
|
|
mpWindowImpl->mpSysObj->UnionClipRegion( nX, nY, nWidth, nHeight );
|
|
bRegionRect = aRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
|
|
}
|
|
mpWindowImpl->mpSysObj->EndSetClipRegion();
|
|
}
|
|
}
|
|
else
|
|
bVisibleState = sal_False;
|
|
}
|
|
|
|
// Visible-Status updaten
|
|
mpWindowImpl->mpSysObj->Show( bVisibleState );
|
|
}
|
|
|
|
return bUpdate;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplUpdateSysObjChildrenClip()
|
|
{
|
|
if ( mpWindowImpl->mpSysObj && mpWindowImpl->mbInitWinClipRegion )
|
|
ImplSysObjClip( NULL );
|
|
|
|
Window* pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
pWindow->ImplUpdateSysObjChildrenClip();
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplUpdateSysObjOverlapsClip()
|
|
{
|
|
ImplUpdateSysObjChildrenClip();
|
|
|
|
Window* pWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pWindow )
|
|
{
|
|
pWindow->ImplUpdateSysObjOverlapsClip();
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplUpdateSysObjClip()
|
|
{
|
|
if ( !ImplIsOverlapWindow() )
|
|
{
|
|
ImplUpdateSysObjChildrenClip();
|
|
|
|
// siblings should recalculate their clip region
|
|
if ( mpWindowImpl->mbClipSiblings )
|
|
{
|
|
Window* pWindow = mpWindowImpl->mpNext;
|
|
while ( pWindow )
|
|
{
|
|
pWindow->ImplUpdateSysObjChildrenClip();
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
mpWindowImpl->mpFrameWindow->ImplUpdateSysObjOverlapsClip();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::ImplSetClipFlagChildren( sal_Bool bSysObjOnlySmaller )
|
|
{
|
|
sal_Bool bUpdate = sal_True;
|
|
if ( mpWindowImpl->mpSysObj )
|
|
{
|
|
Region* pOldRegion = NULL;
|
|
if ( bSysObjOnlySmaller && !mpWindowImpl->mbInitWinClipRegion )
|
|
pOldRegion = new Region( mpWindowImpl->maWinClipRegion );
|
|
|
|
mbInitClipRegion = sal_True;
|
|
mpWindowImpl->mbInitWinClipRegion = sal_True;
|
|
|
|
Window* pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
if ( !pWindow->ImplSetClipFlagChildren( bSysObjOnlySmaller ) )
|
|
bUpdate = sal_False;
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
if ( !ImplSysObjClip( pOldRegion ) )
|
|
{
|
|
mbInitClipRegion = sal_True;
|
|
mpWindowImpl->mbInitWinClipRegion = sal_True;
|
|
bUpdate = sal_False;
|
|
}
|
|
|
|
delete pOldRegion;
|
|
}
|
|
else
|
|
{
|
|
mbInitClipRegion = sal_True;
|
|
mpWindowImpl->mbInitWinClipRegion = sal_True;
|
|
|
|
Window* pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
if ( !pWindow->ImplSetClipFlagChildren( bSysObjOnlySmaller ) )
|
|
bUpdate = sal_False;
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
return bUpdate;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::ImplSetClipFlagOverlapWindows( sal_Bool bSysObjOnlySmaller )
|
|
{
|
|
sal_Bool bUpdate = ImplSetClipFlagChildren( bSysObjOnlySmaller );
|
|
|
|
Window* pWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pWindow )
|
|
{
|
|
if ( !pWindow->ImplSetClipFlagOverlapWindows( bSysObjOnlySmaller ) )
|
|
bUpdate = sal_False;
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
return bUpdate;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::ImplSetClipFlag( sal_Bool bSysObjOnlySmaller )
|
|
{
|
|
if ( !ImplIsOverlapWindow() )
|
|
{
|
|
sal_Bool bUpdate = ImplSetClipFlagChildren( bSysObjOnlySmaller );
|
|
|
|
Window* pParent = ImplGetParent();
|
|
if ( pParent &&
|
|
((pParent->GetStyle() & WB_CLIPCHILDREN) || (mpWindowImpl->mnParentClipMode & PARENTCLIPMODE_CLIP)) )
|
|
{
|
|
pParent->mbInitClipRegion = sal_True;
|
|
pParent->mpWindowImpl->mbInitChildRegion = sal_True;
|
|
}
|
|
|
|
// siblings should recalculate their clip region
|
|
if ( mpWindowImpl->mbClipSiblings )
|
|
{
|
|
Window* pWindow = mpWindowImpl->mpNext;
|
|
while ( pWindow )
|
|
{
|
|
if ( !pWindow->ImplSetClipFlagChildren( bSysObjOnlySmaller ) )
|
|
bUpdate = sal_False;
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
return bUpdate;
|
|
}
|
|
else
|
|
return mpWindowImpl->mpFrameWindow->ImplSetClipFlagOverlapWindows( bSysObjOnlySmaller );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplIntersectWindowClipRegion( Region& rRegion )
|
|
{
|
|
if ( mpWindowImpl->mbInitWinClipRegion )
|
|
ImplInitWinClipRegion();
|
|
|
|
rRegion.Intersect( mpWindowImpl->maWinClipRegion );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplIntersectWindowRegion( Region& rRegion )
|
|
{
|
|
rRegion.Intersect( Rectangle( Point( mnOutOffX, mnOutOffY ),
|
|
Size( mnOutWidth, mnOutHeight ) ) );
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
rRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplExcludeWindowRegion( Region& rRegion )
|
|
{
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
{
|
|
Point aPoint( mnOutOffX, mnOutOffY );
|
|
Region aRegion( Rectangle( aPoint,
|
|
Size( mnOutWidth, mnOutHeight ) ) );
|
|
aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
rRegion.Exclude( aRegion );
|
|
}
|
|
else
|
|
{
|
|
Point aPoint( mnOutOffX, mnOutOffY );
|
|
rRegion.Exclude( Rectangle( aPoint,
|
|
Size( mnOutWidth, mnOutHeight ) ) );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplExcludeOverlapWindows( Region& rRegion )
|
|
{
|
|
Window* pWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible )
|
|
{
|
|
pWindow->ImplExcludeWindowRegion( rRegion );
|
|
pWindow->ImplExcludeOverlapWindows( rRegion );
|
|
}
|
|
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplExcludeOverlapWindows2( Region& rRegion )
|
|
{
|
|
if ( mpWindowImpl->mbReallyVisible )
|
|
ImplExcludeWindowRegion( rRegion );
|
|
|
|
ImplExcludeOverlapWindows( rRegion );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplClipBoundaries( Region& rRegion, sal_Bool bThis, sal_Bool bOverlaps )
|
|
{
|
|
if ( bThis )
|
|
ImplIntersectWindowClipRegion( rRegion );
|
|
else if ( ImplIsOverlapWindow() )
|
|
{
|
|
// clip to frame if required
|
|
if ( !mpWindowImpl->mbFrame )
|
|
rRegion.Intersect( Rectangle( Point( 0, 0 ), Size( mpWindowImpl->mpFrameWindow->mnOutWidth, mpWindowImpl->mpFrameWindow->mnOutHeight ) ) );
|
|
|
|
if ( bOverlaps && !rRegion.IsEmpty() )
|
|
{
|
|
// Clip Overlap Siblings
|
|
Window* pStartOverlapWindow = this;
|
|
while ( !pStartOverlapWindow->mpWindowImpl->mbFrame )
|
|
{
|
|
Window* pOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow && (pOverlapWindow != pStartOverlapWindow) )
|
|
{
|
|
pOverlapWindow->ImplExcludeOverlapWindows2( rRegion );
|
|
pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
}
|
|
pStartOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow;
|
|
}
|
|
|
|
// Clip Child Overlap Windows
|
|
ImplExcludeOverlapWindows( rRegion );
|
|
}
|
|
}
|
|
else
|
|
ImplGetParent()->ImplIntersectWindowClipRegion( rRegion );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::ImplClipChildren( Region& rRegion )
|
|
{
|
|
sal_Bool bOtherClip = sal_False;
|
|
Window* pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible )
|
|
{
|
|
// read-out ParentClipMode-Flags
|
|
sal_uInt16 nClipMode = pWindow->GetParentClipMode();
|
|
if ( !(nClipMode & PARENTCLIPMODE_NOCLIP) &&
|
|
((nClipMode & PARENTCLIPMODE_CLIP) || (GetStyle() & WB_CLIPCHILDREN)) )
|
|
pWindow->ImplExcludeWindowRegion( rRegion );
|
|
else
|
|
bOtherClip = sal_True;
|
|
}
|
|
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
return bOtherClip;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplClipAllChildren( Region& rRegion )
|
|
{
|
|
Window* pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible )
|
|
pWindow->ImplExcludeWindowRegion( rRegion );
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplClipSiblings( Region& rRegion )
|
|
{
|
|
Window* pWindow = ImplGetParent()->mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow == this )
|
|
break;
|
|
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible )
|
|
pWindow->ImplExcludeWindowRegion( rRegion );
|
|
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplInitWinClipRegion()
|
|
{
|
|
// Build Window Region
|
|
mpWindowImpl->maWinClipRegion = Rectangle( Point( mnOutOffX, mnOutOffY ),
|
|
Size( mnOutWidth, mnOutHeight ) );
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
mpWindowImpl->maWinClipRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
|
|
// ClipSiblings
|
|
if ( mpWindowImpl->mbClipSiblings && !ImplIsOverlapWindow() )
|
|
ImplClipSiblings( mpWindowImpl->maWinClipRegion );
|
|
|
|
// Clip Parent Boundaries
|
|
ImplClipBoundaries( mpWindowImpl->maWinClipRegion, sal_False, sal_True );
|
|
|
|
// Clip Children
|
|
if ( (GetStyle() & WB_CLIPCHILDREN) || mpWindowImpl->mbClipChildren )
|
|
mpWindowImpl->mbInitChildRegion = sal_True;
|
|
|
|
mpWindowImpl->mbInitWinClipRegion = sal_False;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplInitWinChildClipRegion()
|
|
{
|
|
if ( !mpWindowImpl->mpFirstChild )
|
|
{
|
|
if ( mpWindowImpl->mpChildClipRegion )
|
|
{
|
|
delete mpWindowImpl->mpChildClipRegion;
|
|
mpWindowImpl->mpChildClipRegion = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !mpWindowImpl->mpChildClipRegion )
|
|
mpWindowImpl->mpChildClipRegion = new Region( mpWindowImpl->maWinClipRegion );
|
|
else
|
|
*mpWindowImpl->mpChildClipRegion = mpWindowImpl->maWinClipRegion;
|
|
|
|
ImplClipChildren( *mpWindowImpl->mpChildClipRegion );
|
|
}
|
|
|
|
mpWindowImpl->mbInitChildRegion = sal_False;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Region* Window::ImplGetWinChildClipRegion()
|
|
{
|
|
if ( mpWindowImpl->mbInitWinClipRegion )
|
|
ImplInitWinClipRegion();
|
|
if ( mpWindowImpl->mbInitChildRegion )
|
|
ImplInitWinChildClipRegion();
|
|
if ( mpWindowImpl->mpChildClipRegion )
|
|
return mpWindowImpl->mpChildClipRegion;
|
|
else
|
|
return &mpWindowImpl->maWinClipRegion;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplIntersectAndUnionOverlapWindows( const Region& rInterRegion, Region& rRegion )
|
|
{
|
|
Window* pWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible )
|
|
{
|
|
Region aTempRegion( rInterRegion );
|
|
pWindow->ImplIntersectWindowRegion( aTempRegion );
|
|
rRegion.Union( aTempRegion );
|
|
pWindow->ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
|
|
}
|
|
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplIntersectAndUnionOverlapWindows2( const Region& rInterRegion, Region& rRegion )
|
|
{
|
|
if ( mpWindowImpl->mbReallyVisible )
|
|
{
|
|
Region aTempRegion( rInterRegion );
|
|
ImplIntersectWindowRegion( aTempRegion );
|
|
rRegion.Union( aTempRegion );
|
|
}
|
|
|
|
ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCalcOverlapRegionOverlaps( const Region& rInterRegion, Region& rRegion )
|
|
{
|
|
// Clip Overlap Siblings
|
|
Window* pStartOverlapWindow;
|
|
if ( !ImplIsOverlapWindow() )
|
|
pStartOverlapWindow = mpWindowImpl->mpOverlapWindow;
|
|
else
|
|
pStartOverlapWindow = this;
|
|
while ( !pStartOverlapWindow->mpWindowImpl->mbFrame )
|
|
{
|
|
Window* pOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow && (pOverlapWindow != pStartOverlapWindow) )
|
|
{
|
|
pOverlapWindow->ImplIntersectAndUnionOverlapWindows2( rInterRegion, rRegion );
|
|
pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
}
|
|
pStartOverlapWindow = pStartOverlapWindow->mpWindowImpl->mpOverlapWindow;
|
|
}
|
|
|
|
// Clip Child Overlap Windows
|
|
if ( !ImplIsOverlapWindow() )
|
|
mpWindowImpl->mpOverlapWindow->ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
|
|
else
|
|
ImplIntersectAndUnionOverlapWindows( rInterRegion, rRegion );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCalcOverlapRegion( const Rectangle& rSourceRect, Region& rRegion,
|
|
sal_Bool bChildren, sal_Bool bParent, sal_Bool bSiblings )
|
|
{
|
|
Region aRegion( rSourceRect );
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
rRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
Region aTempRegion;
|
|
Window* pWindow;
|
|
|
|
ImplCalcOverlapRegionOverlaps( aRegion, rRegion );
|
|
|
|
// Parent-Boundaries
|
|
if ( bParent )
|
|
{
|
|
pWindow = this;
|
|
if ( !ImplIsOverlapWindow() )
|
|
{
|
|
pWindow = ImplGetParent();
|
|
do
|
|
{
|
|
aTempRegion = aRegion;
|
|
pWindow->ImplExcludeWindowRegion( aTempRegion );
|
|
rRegion.Union( aTempRegion );
|
|
if ( pWindow->ImplIsOverlapWindow() )
|
|
break;
|
|
pWindow = pWindow->ImplGetParent();
|
|
}
|
|
while ( pWindow );
|
|
}
|
|
if ( !pWindow->mpWindowImpl->mbFrame )
|
|
{
|
|
aTempRegion = aRegion;
|
|
aTempRegion.Exclude( Rectangle( Point( 0, 0 ), Size( mpWindowImpl->mpFrameWindow->mnOutWidth, mpWindowImpl->mpFrameWindow->mnOutHeight ) ) );
|
|
rRegion.Union( aTempRegion );
|
|
}
|
|
}
|
|
|
|
// Siblings
|
|
if ( bSiblings && !ImplIsOverlapWindow() )
|
|
{
|
|
pWindow = mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild;
|
|
do
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible && (pWindow != this) )
|
|
{
|
|
aTempRegion = aRegion;
|
|
pWindow->ImplIntersectWindowRegion( aTempRegion );
|
|
rRegion.Union( aTempRegion );
|
|
}
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
while ( pWindow );
|
|
}
|
|
|
|
if ( bChildren )
|
|
{
|
|
pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow->mpWindowImpl->mbReallyVisible )
|
|
{
|
|
aTempRegion = aRegion;
|
|
pWindow->ImplIntersectWindowRegion( aTempRegion );
|
|
rRegion.Union( aTempRegion );
|
|
}
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCallPaint( const Region* pRegion, sal_uInt16 nPaintFlags )
|
|
{
|
|
// call PrePaint. PrePaint may add to the invalidate region as well as
|
|
// other parameters used below.
|
|
PrePaint();
|
|
|
|
mpWindowImpl->mbPaintFrame = sal_False;
|
|
|
|
if ( nPaintFlags & IMPL_PAINT_PAINTALLCHILDREN )
|
|
mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINT | IMPL_PAINT_PAINTALLCHILDREN | (nPaintFlags & IMPL_PAINT_PAINTALL);
|
|
if ( nPaintFlags & IMPL_PAINT_PAINTCHILDREN )
|
|
mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTCHILDREN;
|
|
if ( nPaintFlags & IMPL_PAINT_ERASE )
|
|
mpWindowImpl->mnPaintFlags |= IMPL_PAINT_ERASE;
|
|
if ( nPaintFlags & IMPL_PAINT_CHECKRTL )
|
|
mpWindowImpl->mnPaintFlags |= IMPL_PAINT_CHECKRTL;
|
|
if ( !mpWindowImpl->mpFirstChild )
|
|
mpWindowImpl->mnPaintFlags &= ~IMPL_PAINT_PAINTALLCHILDREN;
|
|
|
|
if ( mpWindowImpl->mbPaintDisabled )
|
|
{
|
|
if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
|
|
Invalidate( INVALIDATE_NOCHILDREN | INVALIDATE_NOERASE | INVALIDATE_NOTRANSPARENT | INVALIDATE_NOCLIPCHILDREN );
|
|
else if ( pRegion )
|
|
Invalidate( *pRegion, INVALIDATE_NOCHILDREN | INVALIDATE_NOERASE | INVALIDATE_NOTRANSPARENT | INVALIDATE_NOCLIPCHILDREN );
|
|
return;
|
|
}
|
|
|
|
nPaintFlags = mpWindowImpl->mnPaintFlags & ~(IMPL_PAINT_PAINT);
|
|
|
|
Region* pChildRegion = NULL;
|
|
Rectangle aSelectionRect;
|
|
if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINT )
|
|
{
|
|
Region* pWinChildClipRegion = ImplGetWinChildClipRegion();
|
|
if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
|
|
mpWindowImpl->maInvalidateRegion = *pWinChildClipRegion;
|
|
else
|
|
{
|
|
if ( pRegion )
|
|
mpWindowImpl->maInvalidateRegion.Union( *pRegion );
|
|
|
|
if( mpWindowImpl->mpWinData && mpWindowImpl->mbTrackVisible )
|
|
/* #98602# need to repaint all children within the
|
|
* tracking rectangle, so the following invert
|
|
* operation takes places without traces of the previous
|
|
* one.
|
|
*/
|
|
mpWindowImpl->maInvalidateRegion.Union( *mpWindowImpl->mpWinData->mpTrackRect );
|
|
|
|
if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN )
|
|
pChildRegion = new Region( mpWindowImpl->maInvalidateRegion );
|
|
mpWindowImpl->maInvalidateRegion.Intersect( *pWinChildClipRegion );
|
|
}
|
|
mpWindowImpl->mnPaintFlags = 0;
|
|
if ( !mpWindowImpl->maInvalidateRegion.IsEmpty() )
|
|
{
|
|
bool bRestoreCursor = false;
|
|
if ( mpWindowImpl->mpCursor )
|
|
bRestoreCursor = mpWindowImpl->mpCursor->ImplSuspend();
|
|
|
|
mbInitClipRegion = sal_True;
|
|
mpWindowImpl->mbInPaint = sal_True;
|
|
|
|
// restore Paint-Region
|
|
Region aPaintRegion( mpWindowImpl->maInvalidateRegion );
|
|
Rectangle aPaintRect = aPaintRegion.GetBoundRect();
|
|
|
|
// - RTL - re-mirror paint rect and region at this window
|
|
if( ImplIsAntiparallel() )
|
|
{
|
|
ImplReMirror( aPaintRect );
|
|
ImplReMirror( aPaintRegion );
|
|
}
|
|
aPaintRect = ImplDevicePixelToLogic( aPaintRect);
|
|
mpWindowImpl->mpPaintRegion = &aPaintRegion;
|
|
mpWindowImpl->maInvalidateRegion.SetEmpty();
|
|
|
|
if ( (nPaintFlags & IMPL_PAINT_ERASE) && IsBackground() )
|
|
{
|
|
if ( IsClipRegion() )
|
|
{
|
|
Region aOldRegion = GetClipRegion();
|
|
SetClipRegion();
|
|
Erase();
|
|
SetClipRegion( aOldRegion );
|
|
}
|
|
else
|
|
Erase();
|
|
}
|
|
|
|
// #98943# trigger drawing of toolbox selection after all childern are painted
|
|
if( mpWindowImpl->mbDrawSelectionBackground )
|
|
aSelectionRect = aPaintRect;
|
|
|
|
Paint( aPaintRect );
|
|
|
|
if ( mpWindowImpl->mpWinData )
|
|
{
|
|
if ( mpWindowImpl->mbFocusVisible )
|
|
ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) );
|
|
}
|
|
mpWindowImpl->mbInPaint = sal_False;
|
|
mbInitClipRegion = sal_True;
|
|
mpWindowImpl->mpPaintRegion = NULL;
|
|
if ( mpWindowImpl->mpCursor )
|
|
mpWindowImpl->mpCursor->ImplResume( bRestoreCursor );
|
|
}
|
|
}
|
|
else
|
|
mpWindowImpl->mnPaintFlags = 0;
|
|
|
|
if ( nPaintFlags & (IMPL_PAINT_PAINTALLCHILDREN | IMPL_PAINT_PAINTCHILDREN) )
|
|
{
|
|
// Paint from the bottom child window and frontward.
|
|
Window* pTempWindow = mpWindowImpl->mpLastChild;
|
|
while ( pTempWindow )
|
|
{
|
|
if ( pTempWindow->mpWindowImpl->mbVisible )
|
|
pTempWindow->ImplCallPaint( pChildRegion, nPaintFlags );
|
|
pTempWindow = pTempWindow->mpWindowImpl->mpPrev;
|
|
}
|
|
}
|
|
|
|
if ( mpWindowImpl->mpWinData && mpWindowImpl->mbTrackVisible && (mpWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
|
|
/* #98602# need to invert the tracking rect AFTER
|
|
* the children have painted
|
|
*/
|
|
InvertTracking( *(mpWindowImpl->mpWinData->mpTrackRect), mpWindowImpl->mpWinData->mnTrackFlags );
|
|
|
|
// #98943# draw toolbox selection
|
|
if( !aSelectionRect.IsEmpty() )
|
|
DrawSelectionBackground( aSelectionRect, 3, sal_False, sal_True, sal_False );
|
|
|
|
delete pChildRegion;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCallOverlapPaint()
|
|
{
|
|
// emit overlapping windows first
|
|
Window* pTempWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pTempWindow )
|
|
{
|
|
if ( pTempWindow->mpWindowImpl->mbReallyVisible )
|
|
pTempWindow->ImplCallOverlapPaint();
|
|
pTempWindow = pTempWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
// only then ourself
|
|
if ( mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDREN) )
|
|
{
|
|
// - RTL - notify ImplCallPaint to check for re-mirroring (CHECKRTL)
|
|
// because we were called from the Sal layer
|
|
ImplCallPaint( NULL, mpWindowImpl->mnPaintFlags /*| IMPL_PAINT_CHECKRTL */);
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplPostPaint()
|
|
{
|
|
if ( !mpWindowImpl->mpFrameData->maPaintTimer.IsActive() )
|
|
mpWindowImpl->mpFrameData->maPaintTimer.Start();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK_NOARG(Window, ImplHandlePaintHdl)
|
|
{
|
|
// save paint events until layout is done
|
|
if (IsDialog() && static_cast<const Dialog*>(this)->hasPendingLayout())
|
|
{
|
|
mpWindowImpl->mpFrameData->maPaintTimer.Start();
|
|
return 0;
|
|
}
|
|
|
|
// save paint events until resizing is done
|
|
if( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData->maResizeTimer.IsActive() )
|
|
mpWindowImpl->mpFrameData->maPaintTimer.Start();
|
|
else if ( mpWindowImpl->mbReallyVisible )
|
|
ImplCallOverlapPaint();
|
|
return 0;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK_NOARG(Window, ImplHandleResizeTimerHdl)
|
|
{
|
|
if( mpWindowImpl->mbReallyVisible )
|
|
{
|
|
ImplCallResize();
|
|
if( mpWindowImpl->mpFrameData->maPaintTimer.IsActive() )
|
|
{
|
|
mpWindowImpl->mpFrameData->maPaintTimer.Stop();
|
|
mpWindowImpl->mpFrameData->maPaintTimer.GetTimeoutHdl().Call( NULL );
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplInvalidateFrameRegion( const Region* pRegion, sal_uInt16 nFlags )
|
|
{
|
|
// set PAINTCHILDREN for all parent windows till the first OverlapWindow
|
|
if ( !ImplIsOverlapWindow() )
|
|
{
|
|
Window* pTempWindow = this;
|
|
sal_uInt16 nTranspPaint = IsPaintTransparent() ? IMPL_PAINT_PAINT : 0;
|
|
do
|
|
{
|
|
pTempWindow = pTempWindow->ImplGetParent();
|
|
if ( pTempWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTCHILDREN )
|
|
break;
|
|
pTempWindow->mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTCHILDREN | nTranspPaint;
|
|
if( ! pTempWindow->IsPaintTransparent() )
|
|
nTranspPaint = 0;
|
|
}
|
|
while ( !pTempWindow->ImplIsOverlapWindow() );
|
|
}
|
|
|
|
// set Paint-Flags
|
|
mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINT;
|
|
if ( nFlags & INVALIDATE_CHILDREN )
|
|
mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTALLCHILDREN;
|
|
if ( !(nFlags & INVALIDATE_NOERASE) )
|
|
mpWindowImpl->mnPaintFlags |= IMPL_PAINT_ERASE;
|
|
if ( !pRegion )
|
|
mpWindowImpl->mnPaintFlags |= IMPL_PAINT_PAINTALL;
|
|
|
|
// if not everything has to be redrawn, add the region to it
|
|
if ( !(mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL) )
|
|
mpWindowImpl->maInvalidateRegion.Union( *pRegion );
|
|
|
|
// Handle transparent windows correctly: invalidate must be done on the first opaque parent
|
|
if( ((IsPaintTransparent() && !(nFlags & INVALIDATE_NOTRANSPARENT)) || (nFlags & INVALIDATE_TRANSPARENT) )
|
|
&& ImplGetParent() )
|
|
{
|
|
Window *pParent = ImplGetParent();
|
|
while( pParent && pParent->IsPaintTransparent() )
|
|
pParent = pParent->ImplGetParent();
|
|
if( pParent )
|
|
{
|
|
Region *pChildRegion;
|
|
if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
|
|
// invalidate the whole child window region in the parent
|
|
pChildRegion = ImplGetWinChildClipRegion();
|
|
else
|
|
// invalidate the same region in the parent that has to be repainted in the child
|
|
pChildRegion = &mpWindowImpl->maInvalidateRegion;
|
|
|
|
nFlags |= INVALIDATE_CHILDREN; // paint should also be done on all children
|
|
nFlags &= ~INVALIDATE_NOERASE; // parent should paint and erase to create proper background
|
|
pParent->ImplInvalidateFrameRegion( pChildRegion, nFlags );
|
|
}
|
|
}
|
|
ImplPostPaint();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplInvalidateOverlapFrameRegion( const Region& rRegion )
|
|
{
|
|
Region aRegion = rRegion;
|
|
|
|
ImplClipBoundaries( aRegion, sal_True, sal_True );
|
|
if ( !aRegion.IsEmpty() )
|
|
ImplInvalidateFrameRegion( &aRegion, INVALIDATE_CHILDREN );
|
|
|
|
// now we invalidate the overlapping windows
|
|
Window* pTempWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pTempWindow )
|
|
{
|
|
if ( pTempWindow->IsVisible() )
|
|
pTempWindow->ImplInvalidateOverlapFrameRegion( rRegion );
|
|
|
|
pTempWindow = pTempWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplInvalidateParentFrameRegion( Region& rRegion )
|
|
{
|
|
if ( mpWindowImpl->mbOverlapWin )
|
|
mpWindowImpl->mpFrameWindow->ImplInvalidateOverlapFrameRegion( rRegion );
|
|
else
|
|
{
|
|
if( ImplGetParent() )
|
|
ImplGetParent()->ImplInvalidateFrameRegion( &rRegion, INVALIDATE_CHILDREN );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplInvalidate( const Region* pRegion, sal_uInt16 nFlags )
|
|
{
|
|
|
|
// reset background storage
|
|
if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
|
|
ImplInvalidateAllOverlapBackgrounds();
|
|
|
|
// check what has to be redrawn
|
|
sal_Bool bInvalidateAll = !pRegion;
|
|
|
|
// take Transparent-Invalidate into account
|
|
Window* pOpaqueWindow = this;
|
|
if ( (mpWindowImpl->mbPaintTransparent && !(nFlags & INVALIDATE_NOTRANSPARENT)) || (nFlags & INVALIDATE_TRANSPARENT) )
|
|
{
|
|
Window* pTempWindow = pOpaqueWindow->ImplGetParent();
|
|
while ( pTempWindow )
|
|
{
|
|
if ( !pTempWindow->IsPaintTransparent() )
|
|
{
|
|
pOpaqueWindow = pTempWindow;
|
|
nFlags |= INVALIDATE_CHILDREN;
|
|
bInvalidateAll = sal_False;
|
|
break;
|
|
}
|
|
|
|
if ( pTempWindow->ImplIsOverlapWindow() )
|
|
break;
|
|
|
|
pTempWindow = pTempWindow->ImplGetParent();
|
|
}
|
|
}
|
|
|
|
// assemble region
|
|
sal_uInt16 nOrgFlags = nFlags;
|
|
if ( !(nFlags & (INVALIDATE_CHILDREN | INVALIDATE_NOCHILDREN)) )
|
|
{
|
|
if ( GetStyle() & WB_CLIPCHILDREN )
|
|
nFlags |= INVALIDATE_NOCHILDREN;
|
|
else
|
|
nFlags |= INVALIDATE_CHILDREN;
|
|
}
|
|
if ( (nFlags & INVALIDATE_NOCHILDREN) && mpWindowImpl->mpFirstChild )
|
|
bInvalidateAll = sal_False;
|
|
if ( bInvalidateAll )
|
|
ImplInvalidateFrameRegion( NULL, nFlags );
|
|
else
|
|
{
|
|
Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
Region aRegion( aRect );
|
|
if ( pRegion )
|
|
{
|
|
// --- RTL --- remirror region before intersecting it
|
|
if ( ImplIsAntiparallel() )
|
|
{
|
|
Region aRgn( *pRegion );
|
|
ImplReMirror( aRgn );
|
|
aRegion.Intersect( aRgn );
|
|
}
|
|
else
|
|
aRegion.Intersect( *pRegion );
|
|
}
|
|
ImplClipBoundaries( aRegion, sal_True, sal_True );
|
|
if ( nFlags & INVALIDATE_NOCHILDREN )
|
|
{
|
|
nFlags &= ~INVALIDATE_CHILDREN;
|
|
if ( !(nFlags & INVALIDATE_NOCLIPCHILDREN) )
|
|
{
|
|
if ( nOrgFlags & INVALIDATE_NOCHILDREN )
|
|
ImplClipAllChildren( aRegion );
|
|
else
|
|
{
|
|
if ( ImplClipChildren( aRegion ) )
|
|
nFlags |= INVALIDATE_CHILDREN;
|
|
}
|
|
}
|
|
}
|
|
if ( !aRegion.IsEmpty() )
|
|
ImplInvalidateFrameRegion( &aRegion, nFlags ); // transparency is handled here, pOpaqueWindow not required
|
|
}
|
|
|
|
if ( nFlags & INVALIDATE_UPDATE )
|
|
pOpaqueWindow->Update(); // start painting at the opaque parent
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplMoveInvalidateRegion( const Rectangle& rRect,
|
|
long nHorzScroll, long nVertScroll,
|
|
sal_Bool bChildren )
|
|
{
|
|
if ( (mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTALL)) == IMPL_PAINT_PAINT )
|
|
{
|
|
Region aTempRegion = mpWindowImpl->maInvalidateRegion;
|
|
aTempRegion.Intersect( rRect );
|
|
aTempRegion.Move( nHorzScroll, nVertScroll );
|
|
mpWindowImpl->maInvalidateRegion.Union( aTempRegion );
|
|
}
|
|
|
|
if ( bChildren && (mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTCHILDREN) )
|
|
{
|
|
Window* pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
pWindow->ImplMoveInvalidateRegion( rRect, nHorzScroll, nVertScroll, sal_True );
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplMoveAllInvalidateRegions( const Rectangle& rRect,
|
|
long nHorzScroll, long nVertScroll,
|
|
sal_Bool bChildren )
|
|
{
|
|
// also shift Paint-Region when paints need processing
|
|
ImplMoveInvalidateRegion( rRect, nHorzScroll, nVertScroll, bChildren );
|
|
// Paint-Region should be shifted, as drawn by the parents
|
|
if ( !ImplIsOverlapWindow() )
|
|
{
|
|
Region aPaintAllRegion;
|
|
Window* pPaintAllWindow = this;
|
|
do
|
|
{
|
|
pPaintAllWindow = pPaintAllWindow->ImplGetParent();
|
|
if ( pPaintAllWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN )
|
|
{
|
|
if ( pPaintAllWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
|
|
{
|
|
aPaintAllRegion.SetEmpty();
|
|
break;
|
|
}
|
|
else
|
|
aPaintAllRegion.Union( pPaintAllWindow->mpWindowImpl->maInvalidateRegion );
|
|
}
|
|
}
|
|
while ( !pPaintAllWindow->ImplIsOverlapWindow() );
|
|
if ( !aPaintAllRegion.IsEmpty() )
|
|
{
|
|
aPaintAllRegion.Move( nHorzScroll, nVertScroll );
|
|
sal_uInt16 nPaintFlags = 0;
|
|
if ( bChildren )
|
|
mpWindowImpl->mnPaintFlags |= INVALIDATE_CHILDREN;
|
|
ImplInvalidateFrameRegion( &aPaintAllRegion, nPaintFlags );
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplValidateFrameRegion( const Region* pRegion, sal_uInt16 nFlags )
|
|
{
|
|
if ( !pRegion )
|
|
mpWindowImpl->maInvalidateRegion.SetEmpty();
|
|
else
|
|
{
|
|
// when all child windows have to be drawn we need to invalidate them before doing so
|
|
if ( (mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN) && mpWindowImpl->mpFirstChild )
|
|
{
|
|
Region aChildRegion = mpWindowImpl->maInvalidateRegion;
|
|
if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
|
|
{
|
|
Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
aChildRegion = aRect;
|
|
}
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->Invalidate( aChildRegion, INVALIDATE_CHILDREN | INVALIDATE_NOTRANSPARENT );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALL )
|
|
{
|
|
Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
mpWindowImpl->maInvalidateRegion = aRect;
|
|
}
|
|
mpWindowImpl->maInvalidateRegion.Exclude( *pRegion );
|
|
}
|
|
mpWindowImpl->mnPaintFlags &= ~IMPL_PAINT_PAINTALL;
|
|
|
|
if ( nFlags & VALIDATE_CHILDREN )
|
|
{
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->ImplValidateFrameRegion( pRegion, nFlags );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplValidate( const Region* pRegion, sal_uInt16 nFlags )
|
|
{
|
|
// assemble region
|
|
sal_Bool bValidateAll = !pRegion;
|
|
sal_uInt16 nOrgFlags = nFlags;
|
|
if ( !(nFlags & (VALIDATE_CHILDREN | VALIDATE_NOCHILDREN)) )
|
|
{
|
|
if ( GetStyle() & WB_CLIPCHILDREN )
|
|
nFlags |= VALIDATE_NOCHILDREN;
|
|
else
|
|
nFlags |= VALIDATE_CHILDREN;
|
|
}
|
|
if ( (nFlags & VALIDATE_NOCHILDREN) && mpWindowImpl->mpFirstChild )
|
|
bValidateAll = sal_False;
|
|
if ( bValidateAll )
|
|
ImplValidateFrameRegion( NULL, nFlags );
|
|
else
|
|
{
|
|
Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
Region aRegion( aRect );
|
|
if ( pRegion )
|
|
aRegion.Intersect( *pRegion );
|
|
ImplClipBoundaries( aRegion, sal_True, sal_True );
|
|
if ( nFlags & VALIDATE_NOCHILDREN )
|
|
{
|
|
nFlags &= ~VALIDATE_CHILDREN;
|
|
if ( nOrgFlags & VALIDATE_NOCHILDREN )
|
|
ImplClipAllChildren( aRegion );
|
|
else
|
|
{
|
|
if ( ImplClipChildren( aRegion ) )
|
|
nFlags |= VALIDATE_CHILDREN;
|
|
}
|
|
}
|
|
if ( !aRegion.IsEmpty() )
|
|
ImplValidateFrameRegion( &aRegion, nFlags );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplScroll( const Rectangle& rRect,
|
|
long nHorzScroll, long nVertScroll, sal_uInt16 nFlags )
|
|
{
|
|
if ( !IsDeviceOutputNecessary() )
|
|
return;
|
|
|
|
nHorzScroll = ImplLogicWidthToDevicePixel( nHorzScroll );
|
|
nVertScroll = ImplLogicHeightToDevicePixel( nVertScroll );
|
|
|
|
if ( !nHorzScroll && !nVertScroll )
|
|
return;
|
|
|
|
// restore background storage
|
|
if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
|
|
ImplInvalidateAllOverlapBackgrounds();
|
|
|
|
if ( mpWindowImpl->mpCursor )
|
|
mpWindowImpl->mpCursor->ImplSuspend();
|
|
|
|
sal_uInt16 nOrgFlags = nFlags;
|
|
if ( !(nFlags & (SCROLL_CHILDREN | SCROLL_NOCHILDREN)) )
|
|
{
|
|
if ( GetStyle() & WB_CLIPCHILDREN )
|
|
nFlags |= SCROLL_NOCHILDREN;
|
|
else
|
|
nFlags |= SCROLL_CHILDREN;
|
|
}
|
|
|
|
Region aInvalidateRegion;
|
|
sal_Bool bScrollChildren = (nFlags & SCROLL_CHILDREN) != 0;
|
|
sal_Bool bErase = (nFlags & SCROLL_NOERASE) == 0;
|
|
|
|
if ( !mpWindowImpl->mpFirstChild )
|
|
bScrollChildren = sal_False;
|
|
|
|
// --- RTL --- check if this window requires special action
|
|
sal_Bool bReMirror = ( ImplIsAntiparallel() );
|
|
|
|
Rectangle aRectMirror( rRect );
|
|
if( bReMirror )
|
|
{
|
|
// --- RTL --- make sure the invalidate region of this window is
|
|
// computed in the same coordinate space as the one from the overlap windows
|
|
ImplReMirror( aRectMirror );
|
|
}
|
|
|
|
// adapt paint areas
|
|
ImplMoveAllInvalidateRegions( aRectMirror, nHorzScroll, nVertScroll, bScrollChildren );
|
|
|
|
if ( !(nFlags & SCROLL_NOINVALIDATE) )
|
|
{
|
|
ImplCalcOverlapRegion( aRectMirror, aInvalidateRegion, !bScrollChildren, sal_True, sal_False );
|
|
|
|
// --- RTL ---
|
|
// if the scrolling on the device is performed in the opposite direction
|
|
// then move the overlaps in that direction to compute the invalidate region
|
|
// on the correct side, i.e., revert nHorzScroll
|
|
|
|
if ( !aInvalidateRegion.IsEmpty() )
|
|
{
|
|
aInvalidateRegion.Move( bReMirror ? -nHorzScroll : nHorzScroll, nVertScroll );
|
|
bErase = sal_True;
|
|
}
|
|
if ( !(nFlags & SCROLL_NOWINDOWINVALIDATE) )
|
|
{
|
|
Rectangle aDestRect( aRectMirror );
|
|
aDestRect.Move( bReMirror ? -nHorzScroll : nHorzScroll, nVertScroll );
|
|
Region aWinInvalidateRegion( aRectMirror );
|
|
aWinInvalidateRegion.Exclude( aDestRect );
|
|
|
|
aInvalidateRegion.Union( aWinInvalidateRegion );
|
|
}
|
|
}
|
|
|
|
Point aPoint( mnOutOffX, mnOutOffY );
|
|
Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
|
|
if ( nFlags & SCROLL_CLIP )
|
|
aRegion.Intersect( rRect );
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
|
|
aRegion.Exclude( aInvalidateRegion );
|
|
|
|
ImplClipBoundaries( aRegion, sal_False, sal_True );
|
|
if ( !bScrollChildren )
|
|
{
|
|
if ( nOrgFlags & SCROLL_NOCHILDREN )
|
|
ImplClipAllChildren( aRegion );
|
|
else
|
|
ImplClipChildren( aRegion );
|
|
}
|
|
if ( mbClipRegion && (nFlags & SCROLL_USECLIPREGION) )
|
|
aRegion.Intersect( maRegion );
|
|
if ( !aRegion.IsEmpty() )
|
|
{
|
|
if ( mpWindowImpl->mpWinData )
|
|
{
|
|
if ( mpWindowImpl->mbFocusVisible )
|
|
ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) );
|
|
if ( mpWindowImpl->mbTrackVisible && (mpWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
|
|
InvertTracking( *(mpWindowImpl->mpWinData->mpTrackRect), mpWindowImpl->mpWinData->mnTrackFlags );
|
|
}
|
|
|
|
SalGraphics* pGraphics = ImplGetFrameGraphics();
|
|
if ( pGraphics )
|
|
{
|
|
if( bReMirror )
|
|
{
|
|
// --- RTL --- frame coordinates require re-mirroring
|
|
ImplReMirror( aRegion );
|
|
}
|
|
|
|
ImplSelectClipRegion( aRegion, pGraphics );
|
|
pGraphics->CopyArea( rRect.Left()+nHorzScroll, rRect.Top()+nVertScroll,
|
|
rRect.Left(), rRect.Top(),
|
|
rRect.GetWidth(), rRect.GetHeight(),
|
|
SAL_COPYAREA_WINDOWINVALIDATE, this );
|
|
}
|
|
|
|
if ( mpWindowImpl->mpWinData )
|
|
{
|
|
if ( mpWindowImpl->mbFocusVisible )
|
|
ImplInvertFocus( *(mpWindowImpl->mpWinData->mpFocusRect) );
|
|
if ( mpWindowImpl->mbTrackVisible && (mpWindowImpl->mpWinData->mnTrackFlags & SHOWTRACK_WINDOW) )
|
|
InvertTracking( *(mpWindowImpl->mpWinData->mpTrackRect), mpWindowImpl->mpWinData->mnTrackFlags );
|
|
}
|
|
}
|
|
|
|
if ( !aInvalidateRegion.IsEmpty() )
|
|
{
|
|
// --- RTL --- the invalidate region for this windows is already computed in frame coordinates
|
|
// so it has to be re-mirrored before calling the Paint-handler
|
|
mpWindowImpl->mnPaintFlags |= IMPL_PAINT_CHECKRTL;
|
|
|
|
sal_uInt16 nPaintFlags = INVALIDATE_CHILDREN;
|
|
if ( !bErase )
|
|
nPaintFlags |= INVALIDATE_NOERASE;
|
|
if ( !bScrollChildren )
|
|
{
|
|
if ( nOrgFlags & SCROLL_NOCHILDREN )
|
|
ImplClipAllChildren( aInvalidateRegion );
|
|
else
|
|
ImplClipChildren( aInvalidateRegion );
|
|
}
|
|
ImplInvalidateFrameRegion( &aInvalidateRegion, nPaintFlags );
|
|
}
|
|
|
|
if ( bScrollChildren )
|
|
{
|
|
Window* pWindow = mpWindowImpl->mpFirstChild;
|
|
while ( pWindow )
|
|
{
|
|
Point aPos = pWindow->GetPosPixel();
|
|
aPos += Point( nHorzScroll, nVertScroll );
|
|
pWindow->SetPosPixel( aPos );
|
|
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
if ( nFlags & SCROLL_UPDATE )
|
|
Update();
|
|
|
|
if ( mpWindowImpl->mpCursor )
|
|
mpWindowImpl->mpCursor->ImplResume();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplUpdateAll( sal_Bool bOverlapWindows )
|
|
{
|
|
if ( !mpWindowImpl->mbReallyVisible )
|
|
return;
|
|
|
|
sal_Bool bFlush = sal_False;
|
|
if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame )
|
|
{
|
|
Point aPoint( 0, 0 );
|
|
Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
|
|
ImplInvalidateOverlapFrameRegion( aRegion );
|
|
if ( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) )
|
|
bFlush = sal_True;
|
|
}
|
|
|
|
// an update changes the OverlapWindow, such that for later paints
|
|
// not too much has to be drawn, if ALLCHILDREN etc. is set
|
|
Window* pWindow = ImplGetFirstOverlapWindow();
|
|
if ( bOverlapWindows )
|
|
pWindow->ImplCallOverlapPaint();
|
|
else
|
|
{
|
|
if ( pWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDREN) )
|
|
pWindow->ImplCallPaint( NULL, pWindow->mpWindowImpl->mnPaintFlags );
|
|
}
|
|
|
|
if ( bFlush )
|
|
Flush();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplUpdateWindowPtr( Window* pWindow )
|
|
{
|
|
if ( mpWindowImpl->mpFrameWindow != pWindow->mpWindowImpl->mpFrameWindow )
|
|
{
|
|
// release graphic
|
|
ImplReleaseGraphics();
|
|
}
|
|
|
|
mpWindowImpl->mpFrameData = pWindow->mpWindowImpl->mpFrameData;
|
|
mpWindowImpl->mpFrame = pWindow->mpWindowImpl->mpFrame;
|
|
mpWindowImpl->mpFrameWindow = pWindow->mpWindowImpl->mpFrameWindow;
|
|
if ( pWindow->ImplIsOverlapWindow() )
|
|
mpWindowImpl->mpOverlapWindow = pWindow;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow = pWindow->mpWindowImpl->mpOverlapWindow;
|
|
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->ImplUpdateWindowPtr( pWindow );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplUpdateWindowPtr()
|
|
{
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->ImplUpdateWindowPtr( this );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplUpdateOverlapWindowPtr( sal_Bool bNewFrame )
|
|
{
|
|
sal_Bool bVisible = IsVisible();
|
|
Show( false );
|
|
ImplRemoveWindow( bNewFrame );
|
|
Window* pRealParent = mpWindowImpl->mpRealParent;
|
|
ImplInsertWindow( ImplGetParent() );
|
|
mpWindowImpl->mpRealParent = pRealParent;
|
|
ImplUpdateWindowPtr();
|
|
if ( ImplUpdatePos() )
|
|
ImplUpdateSysObjPos();
|
|
|
|
if ( bNewFrame )
|
|
{
|
|
Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow )
|
|
{
|
|
Window* pNextOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
|
|
pOverlapWindow = pNextOverlapWindow;
|
|
}
|
|
}
|
|
|
|
if ( bVisible )
|
|
Show( true );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::ImplUpdatePos()
|
|
{
|
|
sal_Bool bSysChild = sal_False;
|
|
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
mnOutOffX = mpWindowImpl->mnX;
|
|
mnOutOffY = mpWindowImpl->mnY;
|
|
}
|
|
else
|
|
{
|
|
Window* pParent = ImplGetParent();
|
|
|
|
mnOutOffX = mpWindowImpl->mnX + pParent->mnOutOffX;
|
|
mnOutOffY = mpWindowImpl->mnY + pParent->mnOutOffY;
|
|
}
|
|
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
if ( pChild->ImplUpdatePos() )
|
|
bSysChild = sal_True;
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
if ( mpWindowImpl->mpSysObj )
|
|
bSysChild = sal_True;
|
|
|
|
return bSysChild;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplUpdateSysObjPos()
|
|
{
|
|
if ( mpWindowImpl->mpSysObj )
|
|
mpWindowImpl->mpSysObj->SetPosSize( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight );
|
|
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->ImplUpdateSysObjPos();
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplPosSizeWindow( long nX, long nY,
|
|
long nWidth, long nHeight, sal_uInt16 nFlags )
|
|
{
|
|
sal_Bool bNewPos = sal_False;
|
|
sal_Bool bNewSize = sal_False;
|
|
sal_Bool bCopyBits = sal_False;
|
|
long nOldOutOffX = mnOutOffX;
|
|
long nOldOutOffY = mnOutOffY;
|
|
long nOldOutWidth = mnOutWidth;
|
|
long nOldOutHeight = mnOutHeight;
|
|
Region* pOverlapRegion = NULL;
|
|
Region* pOldRegion = NULL;
|
|
|
|
if ( IsReallyVisible() )
|
|
{
|
|
if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
|
|
ImplInvalidateAllOverlapBackgrounds();
|
|
|
|
Rectangle aOldWinRect( Point( nOldOutOffX, nOldOutOffY ),
|
|
Size( nOldOutWidth, nOldOutHeight ) );
|
|
pOldRegion = new Region( aOldWinRect );
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
pOldRegion->Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
|
|
if ( mnOutWidth && mnOutHeight && !mpWindowImpl->mbPaintTransparent &&
|
|
!mpWindowImpl->mbInitWinClipRegion && !mpWindowImpl->maWinClipRegion.IsEmpty() &&
|
|
!HasPaintEvent() )
|
|
bCopyBits = sal_True;
|
|
}
|
|
|
|
sal_Bool bnXRecycled = sal_False; // avoid duplicate mirroring in RTL case
|
|
if ( nFlags & WINDOW_POSSIZE_WIDTH )
|
|
{
|
|
if(!( nFlags & WINDOW_POSSIZE_X ))
|
|
{
|
|
nX = mpWindowImpl->mnX;
|
|
nFlags |= WINDOW_POSSIZE_X;
|
|
bnXRecycled = sal_True; // we're using a mnX which was already mirrored in RTL case
|
|
}
|
|
|
|
if ( nWidth < 0 )
|
|
nWidth = 0;
|
|
if ( nWidth != mnOutWidth )
|
|
{
|
|
mnOutWidth = nWidth;
|
|
bNewSize = sal_True;
|
|
bCopyBits = sal_False;
|
|
}
|
|
}
|
|
if ( nFlags & WINDOW_POSSIZE_HEIGHT )
|
|
{
|
|
if ( nHeight < 0 )
|
|
nHeight = 0;
|
|
if ( nHeight != mnOutHeight )
|
|
{
|
|
mnOutHeight = nHeight;
|
|
bNewSize = sal_True;
|
|
bCopyBits = sal_False;
|
|
}
|
|
}
|
|
|
|
if ( nFlags & WINDOW_POSSIZE_X )
|
|
{
|
|
long nOrgX = nX;
|
|
// --- RTL --- (compare the screen coordinates)
|
|
Point aPtDev( Point( nX+mnOutOffX, 0 ) );
|
|
if( ImplHasMirroredGraphics() )
|
|
{
|
|
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 Region();
|
|
ImplCalcOverlapRegion( Rectangle( Point( mnOutOffX, mnOutOffY ),
|
|
Size( mnOutWidth, mnOutHeight ) ),
|
|
*pOverlapRegion, sal_False, sal_True, sal_True );
|
|
}
|
|
mpWindowImpl->mnX = nX;
|
|
mpWindowImpl->maPos.X() = nOrgX;
|
|
mpWindowImpl->mnAbsScreenX = aPtDev.X(); // --- RTL --- (store real screen pos)
|
|
bNewPos = sal_True;
|
|
}
|
|
}
|
|
if ( nFlags & WINDOW_POSSIZE_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 Region();
|
|
ImplCalcOverlapRegion( Rectangle( Point( mnOutOffX, mnOutOffY ),
|
|
Size( mnOutWidth, mnOutHeight ) ),
|
|
*pOverlapRegion, sal_False, sal_True, sal_True );
|
|
}
|
|
mpWindowImpl->mnY = nY;
|
|
mpWindowImpl->maPos.Y() = nY;
|
|
bNewPos = sal_True;
|
|
}
|
|
}
|
|
|
|
if ( bNewPos || bNewSize )
|
|
{
|
|
sal_Bool bUpdateSysObjPos = sal_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,
|
|
WINDOW_POSSIZE_X | WINDOW_POSSIZE_Y |
|
|
WINDOW_POSSIZE_WIDTH | WINDOW_POSSIZE_HEIGHT );
|
|
// Wenn wir ein ClientWindow haben, dann hat dieses fuer die
|
|
// Applikation auch die Position des FloatingWindows
|
|
mpWindowImpl->mpClientWindow->mpWindowImpl->maPos = mpWindowImpl->maPos;
|
|
if ( bNewPos )
|
|
{
|
|
if ( mpWindowImpl->mpClientWindow->IsVisible() )
|
|
{
|
|
mpWindowImpl->mpClientWindow->ImplCallMove();
|
|
}
|
|
else
|
|
{
|
|
mpWindowImpl->mpClientWindow->mpWindowImpl->mbCallMove = sal_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 = sal_True;
|
|
if ( bNewSize )
|
|
mpWindowImpl->mbCallResize = sal_True;
|
|
}
|
|
|
|
sal_Bool bUpdateSysObjClip = sal_False;
|
|
if ( IsReallyVisible() )
|
|
{
|
|
if ( bNewPos || bNewSize )
|
|
{
|
|
// reset background storage
|
|
if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mpSaveBackDev )
|
|
ImplDeleteOverlapBackground();
|
|
if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
|
|
ImplInvalidateAllOverlapBackgrounds();
|
|
// set Clip-Flag
|
|
bUpdateSysObjClip = !ImplSetClipFlag( sal_True );
|
|
}
|
|
|
|
// invalidate window content ?
|
|
if ( bNewPos || (mnOutWidth > nOldOutWidth) || (mnOutHeight > nOldOutHeight) )
|
|
{
|
|
if ( bNewPos )
|
|
{
|
|
sal_Bool bInvalidate = sal_False;
|
|
sal_Bool bParentPaint = sal_True;
|
|
if ( !ImplIsOverlapWindow() )
|
|
bParentPaint = mpWindowImpl->mpParent->IsPaintEnabled();
|
|
if ( bCopyBits && bParentPaint && !HasPaintEvent() )
|
|
{
|
|
Point aPoint( mnOutOffX, mnOutOffY );
|
|
Region aRegion( Rectangle( aPoint,
|
|
Size( mnOutWidth, mnOutHeight ) ) );
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
ImplClipBoundaries( aRegion, sal_False, sal_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,
|
|
sal_True );
|
|
SalGraphics* pGraphics = ImplGetFrameGraphics();
|
|
if ( pGraphics )
|
|
{
|
|
const bool bSelectClipRegion = ImplSelectClipRegion( aRegion, pGraphics );
|
|
if ( bSelectClipRegion )
|
|
{
|
|
pGraphics->CopyArea( mnOutOffX, mnOutOffY,
|
|
nOldOutOffX, nOldOutOffY,
|
|
nOldOutWidth, nOldOutHeight,
|
|
SAL_COPYAREA_WINDOWINVALIDATE, this );
|
|
}
|
|
else
|
|
bInvalidate = sal_True;
|
|
}
|
|
else
|
|
bInvalidate = sal_True;
|
|
if ( !bInvalidate )
|
|
{
|
|
if ( !pOverlapRegion->IsEmpty() )
|
|
ImplInvalidateFrameRegion( pOverlapRegion, INVALIDATE_CHILDREN );
|
|
}
|
|
}
|
|
else
|
|
bInvalidate = sal_True;
|
|
}
|
|
else
|
|
bInvalidate = sal_True;
|
|
if ( bInvalidate )
|
|
ImplInvalidateFrameRegion( NULL, INVALIDATE_CHILDREN );
|
|
}
|
|
else
|
|
{
|
|
Point aPoint( mnOutOffX, mnOutOffY );
|
|
Region aRegion( Rectangle( aPoint,
|
|
Size( mnOutWidth, mnOutHeight ) ) );
|
|
aRegion.Exclude( *pOldRegion );
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
aRegion.Intersect( ImplPixelToDevicePixel( mpWindowImpl->maWinRegion ) );
|
|
ImplClipBoundaries( aRegion, sal_False, sal_True );
|
|
if ( !aRegion.IsEmpty() )
|
|
ImplInvalidateFrameRegion( &aRegion, INVALIDATE_CHILDREN );
|
|
}
|
|
}
|
|
|
|
// invalidate Parent or Overlaps
|
|
if ( bNewPos ||
|
|
(mnOutWidth < nOldOutWidth) || (mnOutHeight < nOldOutHeight) )
|
|
{
|
|
Region aRegion( *pOldRegion );
|
|
if ( !mpWindowImpl->mbPaintTransparent )
|
|
ImplExcludeWindowRegion( aRegion );
|
|
ImplClipBoundaries( aRegion, sal_False, sal_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::ImplToBottomChild()
|
|
{
|
|
if ( !ImplIsOverlapWindow() && !mpWindowImpl->mbReallyVisible && (mpWindowImpl->mpParent->mpWindowImpl->mpLastChild != this) )
|
|
{
|
|
// put the window to the end of the list
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
mpWindowImpl->mpPrev = mpWindowImpl->mpParent->mpWindowImpl->mpLastChild;
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = this;
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
mpWindowImpl->mpNext = NULL;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCalcToTop( ImplCalcToTopData* pPrevData )
|
|
{
|
|
DBG_ASSERT( ImplIsOverlapWindow(), "Window::ImplCalcToTop(): Is not a OverlapWindow" );
|
|
|
|
if ( !mpWindowImpl->mbFrame )
|
|
{
|
|
if ( IsReallyVisible() )
|
|
{
|
|
// calculate region, where the window overlaps with other windows
|
|
Point aPoint( mnOutOffX, mnOutOffY );
|
|
Region aRegion( Rectangle( aPoint,
|
|
Size( mnOutWidth, mnOutHeight ) ) );
|
|
Region aInvalidateRegion;
|
|
ImplCalcOverlapRegionOverlaps( aRegion, aInvalidateRegion );
|
|
|
|
if ( !aInvalidateRegion.IsEmpty() )
|
|
{
|
|
ImplCalcToTopData* pData = new ImplCalcToTopData;
|
|
pPrevData->mpNext = pData;
|
|
pData->mpNext = NULL;
|
|
pData->mpWindow = this;
|
|
pData->mpInvalidateRegion = new Region( aInvalidateRegion );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplToTop( sal_uInt16 nFlags )
|
|
{
|
|
DBG_ASSERT( ImplIsOverlapWindow(), "Window::ImplToTop(): Is not a OverlapWindow" );
|
|
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
// on a mouse click in the external window, it is the latter's
|
|
// responsibility to assure our frame is put in front
|
|
if ( !mpWindowImpl->mpFrameData->mbHasFocus &&
|
|
!mpWindowImpl->mpFrameData->mbSysObjFocus &&
|
|
!mpWindowImpl->mpFrameData->mbInSysObjFocusHdl &&
|
|
!mpWindowImpl->mpFrameData->mbInSysObjToTopHdl )
|
|
{
|
|
// do not bring floating windows on the client to top
|
|
if( !ImplGetClientWindow() || !(ImplGetClientWindow()->GetStyle() & WB_SYSTEMFLOATWIN) )
|
|
{
|
|
sal_uInt16 nSysFlags = 0;
|
|
if ( nFlags & TOTOP_RESTOREWHENMIN )
|
|
nSysFlags |= SAL_FRAME_TOTOP_RESTOREWHENMIN;
|
|
if ( nFlags & TOTOP_FOREGROUNDTASK )
|
|
nSysFlags |= SAL_FRAME_TOTOP_FOREGROUNDTASK;
|
|
if ( nFlags & TOTOP_GRABFOCUSONLY )
|
|
nSysFlags |= SAL_FRAME_TOTOP_GRABFOCUS_ONLY;
|
|
mpWindowImpl->mpFrame->ToTop( nSysFlags );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap != this )
|
|
{
|
|
// remove window from the list
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
|
|
|
|
// take AlwaysOnTop into account
|
|
sal_Bool bOnTop = IsAlwaysOnTopEnabled();
|
|
Window* pNextWin = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
|
|
if ( !bOnTop )
|
|
{
|
|
while ( pNextWin )
|
|
{
|
|
if ( !pNextWin->IsAlwaysOnTopEnabled() )
|
|
break;
|
|
pNextWin = pNextWin->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// check TopLevel
|
|
sal_uInt8 nTopLevel = mpWindowImpl->mpOverlapData->mnTopLevel;
|
|
while ( pNextWin )
|
|
{
|
|
if ( (bOnTop != pNextWin->IsAlwaysOnTopEnabled()) ||
|
|
(nTopLevel <= pNextWin->mpWindowImpl->mpOverlapData->mnTopLevel) )
|
|
break;
|
|
pNextWin = pNextWin->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
// add the window to the list again
|
|
mpWindowImpl->mpNext = pNextWin;
|
|
if ( pNextWin )
|
|
{
|
|
mpWindowImpl->mpPrev = pNextWin->mpWindowImpl->mpPrev;
|
|
pNextWin->mpWindowImpl->mpPrev = this;
|
|
}
|
|
else
|
|
{
|
|
mpWindowImpl->mpPrev = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap;
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = this;
|
|
}
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = this;
|
|
|
|
// recalculate ClipRegion of this and all overlapping windows
|
|
if ( IsReallyVisible() )
|
|
{
|
|
// reset background storage
|
|
if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
|
|
ImplInvalidateAllOverlapBackgrounds();
|
|
mpWindowImpl->mpOverlapWindow->ImplSetClipFlagOverlapWindows();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplStartToTop( sal_uInt16 nFlags )
|
|
{
|
|
ImplCalcToTopData aStartData;
|
|
ImplCalcToTopData* pCurData;
|
|
ImplCalcToTopData* pNextData;
|
|
Window* pOverlapWindow;
|
|
if ( ImplIsOverlapWindow() )
|
|
pOverlapWindow = this;
|
|
else
|
|
pOverlapWindow = mpWindowImpl->mpOverlapWindow;
|
|
|
|
// first calculate paint areas
|
|
Window* pTempOverlapWindow = pOverlapWindow;
|
|
aStartData.mpNext = NULL;
|
|
pCurData = &aStartData;
|
|
do
|
|
{
|
|
pTempOverlapWindow->ImplCalcToTop( pCurData );
|
|
if ( pCurData->mpNext )
|
|
pCurData = pCurData->mpNext;
|
|
pTempOverlapWindow = pTempOverlapWindow->mpWindowImpl->mpOverlapWindow;
|
|
}
|
|
while ( !pTempOverlapWindow->mpWindowImpl->mbFrame );
|
|
// next calculate the paint areas of the ChildOverlap windows
|
|
pTempOverlapWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pTempOverlapWindow )
|
|
{
|
|
pTempOverlapWindow->ImplCalcToTop( pCurData );
|
|
if ( pCurData->mpNext )
|
|
pCurData = pCurData->mpNext;
|
|
pTempOverlapWindow = pTempOverlapWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
// and next change the windows list
|
|
pTempOverlapWindow = pOverlapWindow;
|
|
do
|
|
{
|
|
pTempOverlapWindow->ImplToTop( nFlags );
|
|
pTempOverlapWindow = pTempOverlapWindow->mpWindowImpl->mpOverlapWindow;
|
|
}
|
|
while ( !pTempOverlapWindow->mpWindowImpl->mbFrame );
|
|
// as last step invalidate the invalid areas
|
|
pCurData = aStartData.mpNext;
|
|
while ( pCurData )
|
|
{
|
|
pCurData->mpWindow->ImplInvalidateFrameRegion( pCurData->mpInvalidateRegion, INVALIDATE_CHILDREN );
|
|
pNextData = pCurData->mpNext;
|
|
delete pCurData->mpInvalidateRegion;
|
|
delete pCurData;
|
|
pCurData = pNextData;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplFocusToTop( sal_uInt16 nFlags, sal_Bool bReallyVisible )
|
|
{
|
|
// do we need to fetch the focus?
|
|
if ( !(nFlags & TOTOP_NOGRABFOCUS) )
|
|
{
|
|
// first window with GrabFocus-Activate gets the focus
|
|
Window* pFocusWindow = this;
|
|
while ( !pFocusWindow->ImplIsOverlapWindow() )
|
|
{
|
|
// if the window has no BorderWindow, we
|
|
// should always find the belonging BorderWindow
|
|
if ( !pFocusWindow->mpWindowImpl->mpBorderWindow )
|
|
{
|
|
if ( pFocusWindow->mpWindowImpl->mnActivateMode & ACTIVATE_MODE_GRABFOCUS )
|
|
break;
|
|
}
|
|
pFocusWindow = pFocusWindow->ImplGetParent();
|
|
}
|
|
if ( (pFocusWindow->mpWindowImpl->mnActivateMode & ACTIVATE_MODE_GRABFOCUS) &&
|
|
!pFocusWindow->HasChildPathFocus( sal_True ) )
|
|
pFocusWindow->GrabFocus();
|
|
}
|
|
|
|
if ( bReallyVisible )
|
|
ImplGenerateMouseMove();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplShowAllOverlaps()
|
|
{
|
|
Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow )
|
|
{
|
|
if ( pOverlapWindow->mpWindowImpl->mbOverlapVisible )
|
|
{
|
|
pOverlapWindow->Show( true, SHOW_NOACTIVATE );
|
|
pOverlapWindow->mpWindowImpl->mbOverlapVisible = sal_False;
|
|
}
|
|
|
|
pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplHideAllOverlaps()
|
|
{
|
|
Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow )
|
|
{
|
|
if ( pOverlapWindow->IsVisible() )
|
|
{
|
|
pOverlapWindow->mpWindowImpl->mbOverlapVisible = sal_True;
|
|
pOverlapWindow->Show( false );
|
|
}
|
|
|
|
pOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCallMouseMove( sal_uInt16 nMouseCode, sal_Bool bModChanged )
|
|
{
|
|
if ( mpWindowImpl->mpFrameData->mbMouseIn && mpWindowImpl->mpFrameWindow->mpWindowImpl->mbReallyVisible )
|
|
{
|
|
sal_uLong nTime = Time::GetSystemTicks();
|
|
long nX = mpWindowImpl->mpFrameData->mnLastMouseX;
|
|
long nY = mpWindowImpl->mpFrameData->mnLastMouseY;
|
|
sal_uInt16 nCode = nMouseCode;
|
|
sal_uInt16 nMode = mpWindowImpl->mpFrameData->mnMouseMode;
|
|
sal_Bool bLeave;
|
|
// check for MouseLeave
|
|
if ( ((nX < 0) || (nY < 0) ||
|
|
(nX >= mpWindowImpl->mpFrameWindow->mnOutWidth) ||
|
|
(nY >= mpWindowImpl->mpFrameWindow->mnOutHeight)) &&
|
|
!ImplGetSVData()->maWinData.mpCaptureWin )
|
|
bLeave = sal_True;
|
|
else
|
|
bLeave = sal_False;
|
|
nMode |= MOUSE_SYNTHETIC;
|
|
if ( bModChanged )
|
|
nMode |= MOUSE_MODIFIERCHANGED;
|
|
ImplHandleMouseEvent( mpWindowImpl->mpFrameWindow, EVENT_MOUSEMOVE, bLeave, nX, nY, nTime, nCode, nMode );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplGenerateMouseMove()
|
|
{
|
|
if ( !mpWindowImpl->mpFrameData->mnMouseMoveId )
|
|
Application::PostUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId, LINK( mpWindowImpl->mpFrameWindow, Window, ImplGenerateMouseMoveHdl ) );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
IMPL_LINK_NOARG(Window, ImplGenerateMouseMoveHdl)
|
|
{
|
|
mpWindowImpl->mpFrameData->mnMouseMoveId = 0;
|
|
Window* pCaptureWin = ImplGetSVData()->maWinData.mpCaptureWin;
|
|
if( ! pCaptureWin ||
|
|
(pCaptureWin->mpWindowImpl && pCaptureWin->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame)
|
|
)
|
|
{
|
|
ImplCallMouseMove( mpWindowImpl->mpFrameData->mnMouseCode );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplInvertFocus( const Rectangle& rRect )
|
|
{
|
|
InvertTracking( rRect, SHOWTRACK_SMALL | SHOWTRACK_WINDOW );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCallFocusChangeActivate( Window* pNewOverlapWindow,
|
|
Window* pOldOverlapWindow )
|
|
{
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
Window* pNewRealWindow;
|
|
Window* pOldRealWindow;
|
|
Window* pLastRealWindow;
|
|
sal_Bool bCallActivate = sal_True;
|
|
sal_Bool bCallDeactivate = sal_True;
|
|
|
|
pOldRealWindow = pOldOverlapWindow->ImplGetWindow();
|
|
pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
|
|
if ( (pOldRealWindow->GetType() != WINDOW_FLOATINGWINDOW) ||
|
|
pOldRealWindow->GetActivateMode() )
|
|
{
|
|
if ( (pNewRealWindow->GetType() == WINDOW_FLOATINGWINDOW) &&
|
|
!pNewRealWindow->GetActivateMode() )
|
|
{
|
|
pSVData->maWinData.mpLastDeacWin = pOldOverlapWindow;
|
|
bCallDeactivate = sal_False;
|
|
}
|
|
}
|
|
else if ( (pNewRealWindow->GetType() != WINDOW_FLOATINGWINDOW) ||
|
|
pNewRealWindow->GetActivateMode() )
|
|
{
|
|
if ( pSVData->maWinData.mpLastDeacWin )
|
|
{
|
|
if ( pSVData->maWinData.mpLastDeacWin == pNewOverlapWindow )
|
|
bCallActivate = sal_False;
|
|
else
|
|
{
|
|
pLastRealWindow = pSVData->maWinData.mpLastDeacWin->ImplGetWindow();
|
|
pSVData->maWinData.mpLastDeacWin->mpWindowImpl->mbActive = sal_False;
|
|
pSVData->maWinData.mpLastDeacWin->Deactivate();
|
|
if ( pLastRealWindow != pSVData->maWinData.mpLastDeacWin )
|
|
{
|
|
pLastRealWindow->mpWindowImpl->mbActive = sal_True;
|
|
pLastRealWindow->Activate();
|
|
}
|
|
}
|
|
pSVData->maWinData.mpLastDeacWin = NULL;
|
|
}
|
|
}
|
|
|
|
if ( bCallDeactivate )
|
|
{
|
|
if( pOldOverlapWindow->mpWindowImpl->mbActive )
|
|
{
|
|
pOldOverlapWindow->mpWindowImpl->mbActive = sal_False;
|
|
pOldOverlapWindow->Deactivate();
|
|
}
|
|
if ( pOldRealWindow != pOldOverlapWindow )
|
|
{
|
|
if( pOldRealWindow->mpWindowImpl->mbActive )
|
|
{
|
|
pOldRealWindow->mpWindowImpl->mbActive = sal_False;
|
|
pOldRealWindow->Deactivate();
|
|
}
|
|
}
|
|
}
|
|
if ( bCallActivate && ! pNewOverlapWindow->mpWindowImpl->mbActive )
|
|
{
|
|
if( ! pNewOverlapWindow->mpWindowImpl->mbActive )
|
|
{
|
|
pNewOverlapWindow->mpWindowImpl->mbActive = sal_True;
|
|
pNewOverlapWindow->Activate();
|
|
}
|
|
if ( pNewRealWindow != pNewOverlapWindow )
|
|
{
|
|
if( ! pNewRealWindow->mpWindowImpl->mbActive )
|
|
{
|
|
pNewRealWindow->mpWindowImpl->mbActive = sal_True;
|
|
pNewRealWindow->Activate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool IsWindowFocused(const WindowImpl& rWinImpl)
|
|
{
|
|
if (rWinImpl.mpSysObj)
|
|
return true;
|
|
|
|
if (rWinImpl.mpFrameData->mbHasFocus)
|
|
return true;
|
|
|
|
if (rWinImpl.mbFakeFocusSet)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void Window::ImplGrabFocus( sal_uInt16 nFlags )
|
|
{
|
|
// #143570# no focus for destructing windows
|
|
if( mpWindowImpl->mbInDtor )
|
|
return;
|
|
|
|
// some event listeners do really bad stuff
|
|
// => prepare for the worst
|
|
ImplDelData aDogTag( this );
|
|
|
|
// Currently the client window should always get the focus
|
|
// Should the border window at some point be focusable
|
|
// we need to change all GrabFocus() instances in VCL,
|
|
// e.g. in ToTop()
|
|
|
|
if ( mpWindowImpl->mpClientWindow )
|
|
{
|
|
// For a lack of design we need a little hack here to
|
|
// ensure that dialogs on close pass the focus back to
|
|
// the correct window
|
|
if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow != this) &&
|
|
!(mpWindowImpl->mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) &&
|
|
mpWindowImpl->mpLastFocusWindow->IsEnabled() &&
|
|
mpWindowImpl->mpLastFocusWindow->IsInputEnabled() &&
|
|
! mpWindowImpl->mpLastFocusWindow->IsInModalMode()
|
|
)
|
|
mpWindowImpl->mpLastFocusWindow->GrabFocus();
|
|
else
|
|
mpWindowImpl->mpClientWindow->GrabFocus();
|
|
return;
|
|
}
|
|
else if ( mpWindowImpl->mbFrame )
|
|
{
|
|
// For a lack of design we need a little hack here to
|
|
// ensure that dialogs on close pass the focus back to
|
|
// the correct window
|
|
if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow != this) &&
|
|
!(mpWindowImpl->mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) &&
|
|
mpWindowImpl->mpLastFocusWindow->IsEnabled() &&
|
|
mpWindowImpl->mpLastFocusWindow->IsInputEnabled() &&
|
|
! mpWindowImpl->mpLastFocusWindow->IsInModalMode()
|
|
)
|
|
{
|
|
mpWindowImpl->mpLastFocusWindow->GrabFocus();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If the Window is disabled, then we don't change the focus
|
|
if ( !IsEnabled() || !IsInputEnabled() || IsInModalNonRefMode() )
|
|
return;
|
|
|
|
// we only need to set the focus if it is not already set
|
|
// note: if some other frame is waiting for an asynchrounous focus event
|
|
// we also have to post an asynchronous focus event for this frame
|
|
// which is done using ToTop
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
|
|
sal_Bool bAsyncFocusWaiting = sal_False;
|
|
Window *pFrame = pSVData->maWinData.mpFirstFrame;
|
|
while( pFrame )
|
|
{
|
|
if( pFrame != mpWindowImpl->mpFrameWindow && pFrame->mpWindowImpl->mpFrameData->mnFocusId )
|
|
{
|
|
bAsyncFocusWaiting = sal_True;
|
|
break;
|
|
}
|
|
pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
|
|
}
|
|
|
|
bool bHasFocus = IsWindowFocused(*mpWindowImpl);
|
|
|
|
sal_Bool bMustNotGrabFocus = sal_False;
|
|
// #100242#, check parent hierarchy if some floater prohibits grab focus
|
|
|
|
Window *pParent = this;
|
|
while( pParent )
|
|
{
|
|
// #102158#, ignore grabfocus only if the floating parent grabs keyboard focus by itself (GrabsFocus())
|
|
// otherwise we cannot set the focus in a floating toolbox
|
|
if( ( (pParent->mpWindowImpl->mbFloatWin && ((FloatingWindow*)pParent)->GrabsFocus()) || ( pParent->GetStyle() & WB_SYSTEMFLOATWIN ) ) && !( pParent->GetStyle() & WB_MOVEABLE ) )
|
|
{
|
|
bMustNotGrabFocus = sal_True;
|
|
break;
|
|
}
|
|
pParent = pParent->mpWindowImpl->mpParent;
|
|
}
|
|
|
|
|
|
if ( ( pSVData->maWinData.mpFocusWin != this && ! mpWindowImpl->mbInDtor ) || ( bAsyncFocusWaiting && !bHasFocus && !bMustNotGrabFocus ) )
|
|
{
|
|
// EndExtTextInput if it is not the same window
|
|
if ( pSVData->maWinData.mpExtTextInputWin &&
|
|
(pSVData->maWinData.mpExtTextInputWin != this) )
|
|
pSVData->maWinData.mpExtTextInputWin->EndExtTextInput( EXTTEXTINPUT_END_COMPLETE );
|
|
|
|
// mark this windows as the last FocusWindow
|
|
Window* pOverlapWindow = ImplGetFirstOverlapWindow();
|
|
pOverlapWindow->mpWindowImpl->mpLastFocusWindow = this;
|
|
mpWindowImpl->mpFrameData->mpFocusWin = this;
|
|
|
|
if( !bHasFocus )
|
|
{
|
|
// menu windows never get the system focus
|
|
// the application will keep the focus
|
|
if( bMustNotGrabFocus )
|
|
return;
|
|
else
|
|
{
|
|
// here we already switch focus as ToTop()
|
|
// should not give focus to another window
|
|
//DBG_WARNING( "Window::GrabFocus() - Frame doesn't have the focus" );
|
|
mpWindowImpl->mpFrame->ToTop( SAL_FRAME_TOTOP_GRABFOCUS | SAL_FRAME_TOTOP_GRABFOCUS_ONLY );
|
|
return;
|
|
}
|
|
}
|
|
|
|
Window* pOldFocusWindow = pSVData->maWinData.mpFocusWin;
|
|
ImplDelData aOldFocusDel( pOldFocusWindow );
|
|
|
|
pSVData->maWinData.mpFocusWin = this;
|
|
|
|
if ( pOldFocusWindow )
|
|
{
|
|
// Cursor hidden
|
|
if ( pOldFocusWindow->mpWindowImpl->mpCursor )
|
|
pOldFocusWindow->mpWindowImpl->mpCursor->ImplHide( true );
|
|
}
|
|
|
|
// !!!!! due to old SV-Office Activate/Deactivate handling
|
|
// !!!!! first as before
|
|
if ( pOldFocusWindow )
|
|
{
|
|
// remember Focus
|
|
Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow();
|
|
Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
|
|
if ( pOldOverlapWindow != pNewOverlapWindow )
|
|
ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow );
|
|
}
|
|
else
|
|
{
|
|
Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
|
|
Window* pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
|
|
pNewOverlapWindow->mpWindowImpl->mbActive = sal_True;
|
|
pNewOverlapWindow->Activate();
|
|
if ( pNewRealWindow != pNewOverlapWindow )
|
|
{
|
|
pNewRealWindow->mpWindowImpl->mbActive = sal_True;
|
|
pNewRealWindow->Activate();
|
|
}
|
|
}
|
|
|
|
// call Get- and LoseFocus
|
|
if ( pOldFocusWindow && ! aOldFocusDel.IsDead() )
|
|
{
|
|
if ( pOldFocusWindow->IsTracking() &&
|
|
(pSVData->maWinData.mnTrackFlags & STARTTRACK_FOCUSCANCEL) )
|
|
pOldFocusWindow->EndTracking( ENDTRACK_CANCEL | ENDTRACK_FOCUS );
|
|
NotifyEvent aNEvt( EVENT_LOSEFOCUS, pOldFocusWindow );
|
|
if ( !ImplCallPreNotify( aNEvt ) )
|
|
pOldFocusWindow->LoseFocus();
|
|
pOldFocusWindow->ImplCallDeactivateListeners( this );
|
|
}
|
|
|
|
if ( pSVData->maWinData.mpFocusWin == this )
|
|
{
|
|
if ( mpWindowImpl->mpSysObj )
|
|
{
|
|
mpWindowImpl->mpFrameData->mpFocusWin = this;
|
|
if ( !mpWindowImpl->mpFrameData->mbInSysObjFocusHdl )
|
|
mpWindowImpl->mpSysObj->GrabFocus();
|
|
}
|
|
|
|
if ( pSVData->maWinData.mpFocusWin == this )
|
|
{
|
|
if ( mpWindowImpl->mpCursor )
|
|
mpWindowImpl->mpCursor->ImplShow();
|
|
mpWindowImpl->mbInFocusHdl = sal_True;
|
|
mpWindowImpl->mnGetFocusFlags = nFlags;
|
|
// if we're changing focus due to closing a popup floating window
|
|
// notify the new focus window so it can restore the inner focus
|
|
// eg, toolboxes can select their recent active item
|
|
if( pOldFocusWindow &&
|
|
! aOldFocusDel.IsDead() &&
|
|
( pOldFocusWindow->GetDialogControlFlags() & WINDOW_DLGCTRL_FLOATWIN_POPUPMODEEND_CANCEL ) )
|
|
mpWindowImpl->mnGetFocusFlags |= GETFOCUS_FLOATWIN_POPUPMODEEND_CANCEL;
|
|
NotifyEvent aNEvt( EVENT_GETFOCUS, this );
|
|
if ( !ImplCallPreNotify( aNEvt ) && !aDogTag.IsDead() )
|
|
GetFocus();
|
|
if( !aDogTag.IsDead() )
|
|
ImplCallActivateListeners( (pOldFocusWindow && ! aOldFocusDel.IsDead()) ? pOldFocusWindow : NULL );
|
|
if( !aDogTag.IsDead() )
|
|
{
|
|
mpWindowImpl->mnGetFocusFlags = 0;
|
|
mpWindowImpl->mbInFocusHdl = sal_False;
|
|
}
|
|
}
|
|
}
|
|
|
|
GetpApp()->FocusChanged();
|
|
ImplNewInputContext();
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplNewInputContext()
|
|
{
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
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 Font& rFont = rInputContext.GetFont();
|
|
const XubString& rFontName = rFont.GetName();
|
|
ImplFontEntry* pFontEntry = NULL;
|
|
aNewContext.mpFont = NULL;
|
|
if ( rFontName.Len() )
|
|
{
|
|
Size aSize = pFocusWin->ImplLogicToDevicePixel( rFont.GetSize() );
|
|
if ( !aSize.Height() )
|
|
{
|
|
// only set default sizes if the font height in logical
|
|
// coordinates equals 0
|
|
if ( rFont.GetSize().Height() )
|
|
aSize.Height() = 1;
|
|
else
|
|
aSize.Height() = (12*pFocusWin->mnDPIY)/72;
|
|
}
|
|
// TODO: No display device uses ImplDirectFontSubstitution thingy, right? => remove it
|
|
ImplDirectFontSubstitution* pFontSubst = NULL;
|
|
//if( pFocusWin->mpOutDevData )
|
|
// pFontSubst = &pFocusWin->mpOutDevData->maDevFontSubst;
|
|
pFontEntry = pFocusWin->mpFontCache->GetFontEntry( pFocusWin->mpFontList,
|
|
rFont, aSize, static_cast<float>(aSize.Height()), pFontSubst );
|
|
if ( pFontEntry )
|
|
aNewContext.mpFont = &pFontEntry->maFontSelData;
|
|
}
|
|
aNewContext.meLanguage = rFont.GetLanguage();
|
|
aNewContext.mnOptions = rInputContext.GetOptions();
|
|
pFocusWin->ImplGetFrame()->SetInputContext( &aNewContext );
|
|
|
|
if ( pFontEntry )
|
|
pFocusWin->mpFontCache->Release( pFontEntry );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Window::Window( WindowType nType )
|
|
{
|
|
DBG_CTOR( Window, ImplDbgCheckWindow );
|
|
|
|
ImplInitWindowData( nType );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Window::Window( Window* pParent, WinBits nStyle )
|
|
{
|
|
DBG_CTOR( Window, ImplDbgCheckWindow );
|
|
|
|
ImplInitWindowData( WINDOW_WINDOW );
|
|
ImplInit( pParent, nStyle, NULL );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Window::Window( Window* pParent, const ResId& rResId )
|
|
: mpWindowImpl(NULL)
|
|
{
|
|
DBG_CTOR( Window, ImplDbgCheckWindow );
|
|
|
|
rResId.SetRT( RSC_WINDOW );
|
|
WinBits nStyle = ImplInitRes( rResId );
|
|
ImplInitWindowData( WINDOW_WINDOW );
|
|
ImplInit( pParent, nStyle, NULL );
|
|
ImplLoadRes( rResId );
|
|
|
|
if ( !(nStyle & WB_HIDE) )
|
|
Show();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
namespace
|
|
{
|
|
rtl::OString lcl_createWindowInfo(const Window& i_rWindow)
|
|
{
|
|
// skip border windows, they don't carry information which helps diagnosing the problem
|
|
const Window* pWindow( &i_rWindow );
|
|
while ( pWindow && ( pWindow->GetType() == WINDOW_BORDERWINDOW ) )
|
|
pWindow = pWindow->GetWindow( WINDOW_FIRSTCHILD );
|
|
if ( !pWindow )
|
|
pWindow = &i_rWindow;
|
|
|
|
rtl::OStringBuffer aErrorString;
|
|
aErrorString.append(char(13));
|
|
aErrorString.append(typeid( *pWindow ).name());
|
|
aErrorString.append(" (window text: '");
|
|
aErrorString.append(rtl::OUStringToOString(pWindow->GetText(), RTL_TEXTENCODING_UTF8));
|
|
aErrorString.append("')");
|
|
return aErrorString.makeStringAndClear();
|
|
}
|
|
}
|
|
#endif
|
|
// -----------------------------------------------------------------------
|
|
|
|
Window::~Window()
|
|
{
|
|
vcl::LazyDeletor<Window>::Undelete( this );
|
|
|
|
DBG_DTOR( Window, ImplDbgCheckWindow );
|
|
DBG_ASSERT( !mpWindowImpl->mbInDtor, "~Window - already in DTOR!" );
|
|
|
|
|
|
// 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.
|
|
uno::Reference< rendering::XCanvas > xCanvas( mpWindowImpl->mxCanvas );
|
|
if( xCanvas.is() )
|
|
{
|
|
uno::Reference < lang::XComponent > xCanvasComponent( xCanvas,
|
|
uno::UNO_QUERY );
|
|
if( xCanvasComponent.is() )
|
|
xCanvasComponent->dispose();
|
|
}
|
|
|
|
mpWindowImpl->mbInDtor = sal_True;
|
|
|
|
ImplCallEventListeners( VCLEVENT_OBJECT_DYING );
|
|
|
|
// do not send child events for frames that were registered as native frames
|
|
if( !ImplIsAccessibleNativeFrame() && mpWindowImpl->mbReallyVisible )
|
|
if ( ImplIsAccessibleCandidate() && GetAccessibleParentWindow() )
|
|
GetAccessibleParentWindow()->ImplCallEventListeners( 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< Window* >& rList = ImplGetOwnerDrawList();
|
|
::std::vector< Window* >::iterator p;
|
|
p = ::std::find( rList.begin(), rList.end(), this );
|
|
if( p != rList.end() )
|
|
rList.erase( p );
|
|
}
|
|
|
|
// shutdown drag and drop
|
|
::com::sun::star::uno::Reference < ::com::sun::star::lang::XComponent > xDnDComponent( mpWindowImpl->mxDNDListenerContainer, ::com::sun::star::uno::UNO_QUERY );
|
|
|
|
if( xDnDComponent.is() )
|
|
xDnDComponent->dispose();
|
|
|
|
if( mpWindowImpl->mbFrame && mpWindowImpl->mpFrameData )
|
|
{
|
|
try
|
|
{
|
|
// deregister drop target listener
|
|
if( mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
|
|
{
|
|
uno::Reference< XDragGestureRecognizer > xDragGestureRecognizer =
|
|
uno::Reference< XDragGestureRecognizer > (mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
|
|
if( xDragGestureRecognizer.is() )
|
|
{
|
|
xDragGestureRecognizer->removeDragGestureListener(
|
|
uno::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
|
|
uno::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( sal_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() )
|
|
{
|
|
::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent> xC( mpWindowImpl->mxAccessible, ::com::sun::star::uno::UNO_QUERY );
|
|
if ( xC.is() )
|
|
xC->dispose();
|
|
}
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
|
|
if ( pSVData->maHelpData.mpHelpWin && (pSVData->maHelpData.mpHelpWin->GetParent() == this) )
|
|
ImplDestroyHelpWindow( true );
|
|
|
|
DBG_ASSERT( pSVData->maWinData.mpTrackWin != this,
|
|
"Window::~Window(): Window is in TrackingMode" );
|
|
DBG_ASSERT( pSVData->maWinData.mpCaptureWin != this,
|
|
"Window::~Window(): Window has the mouse captured" );
|
|
// #103442# DefModalDialogParent is now determined on-the-fly, so this pointer is unimportant now
|
|
//DBG_ASSERT( pSVData->maWinData.mpDefDialogParent != this,
|
|
// "Window::~Window(): Window is DefModalDialogParent" );
|
|
|
|
// due to old compatibility
|
|
if ( pSVData->maWinData.mpTrackWin == this )
|
|
EndTracking();
|
|
if ( pSVData->maWinData.mpCaptureWin == this )
|
|
ReleaseMouse();
|
|
if ( pSVData->maWinData.mpDefDialogParent == this )
|
|
pSVData->maWinData.mpDefDialogParent = NULL;
|
|
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
if ( sal_True ) // always perform these tests in non-pro versions
|
|
{
|
|
rtl::OStringBuffer aErrorStr;
|
|
sal_Bool bError = sal_False;
|
|
Window* pTempWin;
|
|
if (mpWindowImpl->mpFrameData != 0)
|
|
{
|
|
pTempWin = mpWindowImpl->mpFrameData->mpFirstOverlap;
|
|
while ( pTempWin )
|
|
{
|
|
if ( ImplIsRealParentPath( pTempWin ) )
|
|
{
|
|
bError = sal_True;
|
|
aErrorStr.append(lcl_createWindowInfo(*pTempWin));
|
|
}
|
|
pTempWin = pTempWin->mpWindowImpl->mpNextOverlap;
|
|
}
|
|
if ( bError )
|
|
{
|
|
rtl::OStringBuffer aTempStr;
|
|
aTempStr.append("Window (");
|
|
aTempStr.append(rtl::OUStringToOString(GetText(),
|
|
RTL_TEXTENCODING_UTF8));
|
|
aTempStr.append(") with living SystemWindow(s) destroyed: ");
|
|
aTempStr.append(aErrorStr.toString());
|
|
OSL_FAIL(aTempStr.getStr());
|
|
// abort in non-pro version, this must be fixed!
|
|
GetpApp()->Abort(rtl::OStringToOUString(
|
|
aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
|
|
}
|
|
}
|
|
|
|
bError = sal_False;
|
|
pTempWin = pSVData->maWinData.mpFirstFrame;
|
|
while ( pTempWin )
|
|
{
|
|
if ( ImplIsRealParentPath( pTempWin ) )
|
|
{
|
|
bError = sal_True;
|
|
aErrorStr.append(lcl_createWindowInfo(*pTempWin));
|
|
}
|
|
pTempWin = pTempWin->mpWindowImpl->mpFrameData->mpNextFrame;
|
|
}
|
|
if ( bError )
|
|
{
|
|
rtl::OStringBuffer aTempStr( "Window (" );
|
|
aTempStr.append(rtl::OUStringToOString(GetText(), RTL_TEXTENCODING_UTF8));
|
|
aTempStr.append(") with living SystemWindow(s) destroyed: ");
|
|
aTempStr.append(aErrorStr.toString());
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
GetpApp()->Abort(rtl::OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in non-pro version, this must be fixed!
|
|
}
|
|
|
|
if ( mpWindowImpl->mpFirstChild )
|
|
{
|
|
rtl::OStringBuffer aTempStr("Window (");
|
|
aTempStr.append(rtl::OUStringToOString(GetText(), RTL_TEXTENCODING_UTF8));
|
|
aTempStr.append(") with living Child(s) destroyed: ");
|
|
pTempWin = mpWindowImpl->mpFirstChild;
|
|
while ( pTempWin )
|
|
{
|
|
aTempStr.append(lcl_createWindowInfo(*pTempWin));
|
|
pTempWin = pTempWin->mpWindowImpl->mpNext;
|
|
}
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
GetpApp()->Abort(rtl::OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in non-pro version, this must be fixed!
|
|
}
|
|
|
|
if ( mpWindowImpl->mpFirstOverlap )
|
|
{
|
|
rtl::OStringBuffer aTempStr("Window (");
|
|
aTempStr.append(rtl::OUStringToOString(GetText(), RTL_TEXTENCODING_UTF8));
|
|
aTempStr.append(") with living SystemWindow(s) destroyed: ");
|
|
pTempWin = mpWindowImpl->mpFirstOverlap;
|
|
while ( pTempWin )
|
|
{
|
|
aTempStr.append(lcl_createWindowInfo(*pTempWin));
|
|
pTempWin = pTempWin->mpWindowImpl->mpNext;
|
|
}
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
GetpApp()->Abort(rtl::OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in non-pro version, this must be fixed!
|
|
}
|
|
|
|
Window* pMyParent = this;
|
|
SystemWindow* pMySysWin = NULL;
|
|
|
|
while ( pMyParent )
|
|
{
|
|
if ( pMyParent->IsSystemWindow() )
|
|
pMySysWin = (SystemWindow*)pMyParent;
|
|
pMyParent = pMyParent->GetParent();
|
|
}
|
|
if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
|
|
{
|
|
rtl::OStringBuffer aTempStr("Window (");
|
|
aTempStr.append(rtl::OUStringToOString(GetText(), RTL_TEXTENCODING_UTF8));
|
|
aTempStr.append(") still in TaskPanelList!");
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
GetpApp()->Abort(rtl::OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8)); // abort in non-pro version, this must be fixed!
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if( mpWindowImpl->mbIsInTaskPaneList )
|
|
{
|
|
Window* pMyParent = this;
|
|
SystemWindow* pMySysWin = NULL;
|
|
|
|
while ( pMyParent )
|
|
{
|
|
if ( pMyParent->IsSystemWindow() )
|
|
pMySysWin = (SystemWindow*)pMyParent;
|
|
pMyParent = pMyParent->GetParent();
|
|
}
|
|
if ( pMySysWin && pMySysWin->ImplIsInTaskPaneList( this ) )
|
|
{
|
|
pMySysWin->GetTaskPaneList()->RemoveWindow( this );
|
|
}
|
|
else
|
|
{
|
|
rtl::OStringBuffer aTempStr("Window (");
|
|
aTempStr.append(rtl::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<FixedText*> aMnemonicLabels(list_mnemonic_labels());
|
|
for (std::vector<FixedText*>::iterator 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( EVENT_DESTROY, this );
|
|
Notify( aNEvt );
|
|
}
|
|
|
|
// EndExtTextInputMode
|
|
if ( pSVData->maWinData.mpExtTextInputWin == this )
|
|
{
|
|
EndExtTextInput( EXTTEXTINPUT_END_COMPLETE );
|
|
if ( pSVData->maWinData.mpExtTextInputWin == this )
|
|
pSVData->maWinData.mpExtTextInputWin = NULL;
|
|
}
|
|
|
|
// check if the focus window is our child
|
|
sal_Bool bHasFocussedChild = sal_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 = sal_True;
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
rtl::OStringBuffer aTempStr("Window (");
|
|
aTempStr.append(rtl::OUStringToOString(GetText(),
|
|
RTL_TEXTENCODING_UTF8)).
|
|
append(") with focussed child window destroyed ! THIS WILL LEAD TO CRASHES AND MUST BE FIXED !");
|
|
OSL_FAIL( aTempStr.getStr() );
|
|
GetpApp()->Abort(rtl::OStringToOUString(aTempStr.makeStringAndClear(), RTL_TEXTENCODING_UTF8 )); // abort in non-pro version, this must be fixed!
|
|
#endif
|
|
}
|
|
|
|
// if we get focus pass focus to another window
|
|
Window* pOverlapWindow = ImplGetFirstOverlapWindow();
|
|
if ( pSVData->maWinData.mpFocusWin == this
|
|
|| bHasFocussedChild ) // #122232#, see above, try some cleanup
|
|
{
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
pSVData->maWinData.mpFocusWin = NULL;
|
|
pOverlapWindow->mpWindowImpl->mpLastFocusWindow = NULL;
|
|
GetpApp()->FocusChanged();
|
|
}
|
|
else
|
|
{
|
|
Window* pParent = GetParent();
|
|
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 = NULL;
|
|
pOverlapWindow->mpWindowImpl->mpLastFocusWindow = NULL;
|
|
GetpApp()->FocusChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if ( pOverlapWindow != 0 &&
|
|
pOverlapWindow->mpWindowImpl->mpLastFocusWindow == this )
|
|
pOverlapWindow->mpWindowImpl->mpLastFocusWindow = NULL;
|
|
|
|
// reset hint for DefModalDialogParent
|
|
if( pSVData->maWinData.mpActiveApplicationFrame == this )
|
|
pSVData->maWinData.mpActiveApplicationFrame = NULL;
|
|
|
|
// reset marked windows
|
|
if ( mpWindowImpl->mpFrameData != 0 )
|
|
{
|
|
if ( mpWindowImpl->mpFrameData->mpFocusWin == this )
|
|
mpWindowImpl->mpFrameData->mpFocusWin = NULL;
|
|
if ( mpWindowImpl->mpFrameData->mpMouseMoveWin == this )
|
|
mpWindowImpl->mpFrameData->mpMouseMoveWin = NULL;
|
|
if ( mpWindowImpl->mpFrameData->mpMouseDownWin == this )
|
|
mpWindowImpl->mpFrameData->mpMouseDownWin = NULL;
|
|
}
|
|
|
|
// reset Deactivate-Window
|
|
if ( pSVData->maWinData.mpLastDeacWin == this )
|
|
pSVData->maWinData.mpLastDeacWin = NULL;
|
|
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
if ( mpWindowImpl->mpFrameData->mnFocusId )
|
|
Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnFocusId );
|
|
if ( mpWindowImpl->mpFrameData->mnMouseMoveId )
|
|
Application::RemoveUserEvent( mpWindowImpl->mpFrameData->mnMouseMoveId );
|
|
}
|
|
|
|
// release Graphic
|
|
ImplReleaseGraphics();
|
|
|
|
// if appropriate announce the window has been deleted
|
|
ImplDelData* pDelData = mpWindowImpl->mpFirstDel;
|
|
while ( pDelData )
|
|
{
|
|
pDelData->mbDel = sal_True;
|
|
pDelData->mpWindow = NULL; // #112873# pDel is not associated with a Window anymore
|
|
pDelData = pDelData->mpNext;
|
|
}
|
|
|
|
// remove window from the lists
|
|
ImplRemoveWindow( sal_True );
|
|
|
|
// de-register as "top window child" at our parent, if necessary
|
|
if ( mpWindowImpl->mbFrame )
|
|
{
|
|
sal_Bool bIsTopWindow = mpWindowImpl->mpWinData && ( mpWindowImpl->mpWinData->mnIsTopWindow == 1 );
|
|
if ( mpWindowImpl->mpRealParent && bIsTopWindow )
|
|
{
|
|
ImplWinData* pParentWinData = mpWindowImpl->mpRealParent->ImplGetWinData();
|
|
|
|
::std::list< Window* >::iterator myPos = ::std::find( pParentWinData->maTopWindowChildren.begin(),
|
|
pParentWinData->maTopWindowChildren.end(), this );
|
|
DBG_ASSERT( myPos != pParentWinData->maTopWindowChildren.end(), "Window::~Window: inconsistency in top window chain!" );
|
|
if ( myPos != pParentWinData->maTopWindowChildren.end() )
|
|
pParentWinData->maTopWindowChildren.erase( myPos );
|
|
}
|
|
}
|
|
|
|
// delete extra window data
|
|
if ( mpWindowImpl->mpWinData )
|
|
{
|
|
if ( mpWindowImpl->mpWinData->mpExtOldText )
|
|
delete mpWindowImpl->mpWinData->mpExtOldText;
|
|
if ( mpWindowImpl->mpWinData->mpExtOldAttrAry )
|
|
delete mpWindowImpl->mpWinData->mpExtOldAttrAry;
|
|
if ( mpWindowImpl->mpWinData->mpCursorRect )
|
|
delete mpWindowImpl->mpWinData->mpCursorRect;
|
|
if ( mpWindowImpl->mpWinData->mpFocusRect )
|
|
delete mpWindowImpl->mpWinData->mpFocusRect;
|
|
if ( mpWindowImpl->mpWinData->mpTrackRect )
|
|
delete mpWindowImpl->mpWinData->mpTrackRect;
|
|
|
|
delete mpWindowImpl->mpWinData;
|
|
}
|
|
|
|
|
|
// delete Overlap-Window data
|
|
if ( mpWindowImpl->mpOverlapData )
|
|
{
|
|
delete mpWindowImpl->mpOverlapData;
|
|
}
|
|
|
|
// delete BorderWindow or Frame if required
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
delete mpWindowImpl->mpBorderWindow;
|
|
else if ( mpWindowImpl->mbFrame )
|
|
{
|
|
if ( pSVData->maWinData.mpFirstFrame == this )
|
|
pSVData->maWinData.mpFirstFrame = mpWindowImpl->mpFrameData->mpNextFrame;
|
|
else
|
|
{
|
|
Window* pSysWin = pSVData->maWinData.mpFirstFrame;
|
|
while ( pSysWin->mpWindowImpl->mpFrameData->mpNextFrame != this )
|
|
pSysWin = pSysWin->mpWindowImpl->mpFrameData->mpNextFrame;
|
|
pSysWin->mpWindowImpl->mpFrameData->mpNextFrame = mpWindowImpl->mpFrameData->mpNextFrame;
|
|
}
|
|
mpWindowImpl->mpFrame->SetCallback( NULL, NULL );
|
|
pSVData->mpDefInst->DestroyFrame( mpWindowImpl->mpFrame );
|
|
delete mpWindowImpl->mpFrameData;
|
|
}
|
|
|
|
if ( mpWindowImpl->mpChildClipRegion )
|
|
delete mpWindowImpl->mpChildClipRegion;
|
|
|
|
delete mpWindowImpl->mpAccessibleInfos;
|
|
delete mpWindowImpl->mpControlFont;
|
|
|
|
// should be the last statements
|
|
delete mpWindowImpl; mpWindowImpl = NULL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
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<Window>::Delete( this );
|
|
}
|
|
|
|
sal_uInt16 Window::GetIndicatorState() const
|
|
{
|
|
return mpWindowImpl->mpFrame->GetIndicatorState().mnState;
|
|
}
|
|
|
|
void Window::SimulateKeyPress( sal_uInt16 nKeyCode ) const
|
|
{
|
|
mpWindowImpl->mpFrame->SimulateKeyPress(nKeyCode);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::MouseMove( const MouseEvent& rMEvt )
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
NotifyEvent aNEvt( EVENT_MOUSEMOVE, this, &rMEvt );
|
|
if ( !Notify( aNEvt ) )
|
|
mpWindowImpl->mbMouseMove = sal_True;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::MouseButtonDown( const MouseEvent& rMEvt )
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
NotifyEvent aNEvt( EVENT_MOUSEBUTTONDOWN, this, &rMEvt );
|
|
if ( !Notify( aNEvt ) )
|
|
mpWindowImpl->mbMouseButtonDown = sal_True;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::MouseButtonUp( const MouseEvent& rMEvt )
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
NotifyEvent aNEvt( EVENT_MOUSEBUTTONUP, this, &rMEvt );
|
|
if ( !Notify( aNEvt ) )
|
|
mpWindowImpl->mbMouseButtonUp = sal_True;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::KeyInput( const KeyEvent& rKEvt )
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
NotifyEvent aNEvt( EVENT_KEYINPUT, this, &rKEvt );
|
|
if ( !Notify( aNEvt ) )
|
|
mpWindowImpl->mbKeyInput = sal_True;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::KeyUp( const KeyEvent& rKEvt )
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
NotifyEvent aNEvt( EVENT_KEYUP, this, &rKEvt );
|
|
if ( !Notify( aNEvt ) )
|
|
mpWindowImpl->mbKeyUp = sal_True;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::PrePaint()
|
|
{
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Paint( const Rectangle& rRect )
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_PAINT, (void*)&rRect );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::PostPaint()
|
|
{
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Draw( OutputDevice*, const Point&, const Size&, sal_uLong )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Move()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Resize()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Activate()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Deactivate()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::GetFocus()
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
if ( HasFocus() && mpWindowImpl->mpLastFocusWindow && !(mpWindowImpl->mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) )
|
|
{
|
|
ImplDelData aDogtag( this );
|
|
mpWindowImpl->mpLastFocusWindow->GrabFocus();
|
|
if( aDogtag.IsDead() )
|
|
return;
|
|
}
|
|
|
|
NotifyEvent aNEvt( EVENT_GETFOCUS, this );
|
|
Notify( aNEvt );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::LoseFocus()
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
NotifyEvent aNEvt( EVENT_LOSEFOCUS, this );
|
|
Notify( aNEvt );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::RequestHelp( const HelpEvent& rHEvt )
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
// if Balloon-Help is requested, show the balloon
|
|
// with help text set
|
|
if ( rHEvt.GetMode() & HELPMODE_BALLOON )
|
|
{
|
|
const XubString* pStr = &(GetHelpText());
|
|
if ( !pStr->Len() )
|
|
pStr = &(GetQuickHelpText());
|
|
if ( !pStr->Len() && ImplGetParent() && !ImplIsOverlapWindow() )
|
|
ImplGetParent()->RequestHelp( rHEvt );
|
|
else
|
|
Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), *pStr );
|
|
}
|
|
else if ( rHEvt.GetMode() & HELPMODE_QUICK )
|
|
{
|
|
const XubString* pStr = &(GetQuickHelpText());
|
|
if ( !pStr->Len() && ImplGetParent() && !ImplIsOverlapWindow() )
|
|
ImplGetParent()->RequestHelp( rHEvt );
|
|
else
|
|
{
|
|
Point aPos = GetPosPixel();
|
|
if ( ImplGetParent() && !ImplIsOverlapWindow() )
|
|
aPos = ImplGetParent()->OutputToScreenPixel( aPos );
|
|
Rectangle aRect( aPos, GetSizePixel() );
|
|
String aHelpText;
|
|
if ( pStr->Len() )
|
|
aHelpText = GetHelpText();
|
|
Help::ShowQuickHelp( this, aRect, *pStr, aHelpText, QUICKHELP_CTRLTEXT );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
String aStrHelpId( rtl::OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
|
|
if ( aStrHelpId.Len() == 0 && ImplGetParent() )
|
|
ImplGetParent()->RequestHelp( rHEvt );
|
|
else
|
|
{
|
|
Help* pHelp = Application::GetHelp();
|
|
if ( pHelp )
|
|
{
|
|
if( aStrHelpId.Len() > 0 )
|
|
pHelp->Start( aStrHelpId, this );
|
|
else
|
|
pHelp->Start( rtl::OUString( OOO_HELP_INDEX ), this );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Command( const CommandEvent& rCEvt )
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_COMMAND, (void*)&rCEvt );
|
|
|
|
NotifyEvent aNEvt( EVENT_COMMAND, this, &rCEvt );
|
|
if ( !Notify( aNEvt ) )
|
|
mpWindowImpl->mbCommand = sal_True;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Tracking( const TrackingEvent& rTEvt )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
|
|
if( pWrapper )
|
|
pWrapper->Tracking( rTEvt );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::UserEvent( sal_uLong, void* )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::StateChanged( StateChangedType eType )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
switch (eType)
|
|
{
|
|
//stuff that doesn't invalidate the layout
|
|
case STATE_CHANGE_CONTROLFOREGROUND:
|
|
case STATE_CHANGE_CONTROLBACKGROUND:
|
|
case STATE_CHANGE_TRANSPARENT:
|
|
case STATE_CHANGE_UPDATEMODE:
|
|
case STATE_CHANGE_READONLY:
|
|
case STATE_CHANGE_ENABLE:
|
|
case STATE_CHANGE_STATE:
|
|
case STATE_CHANGE_DATA:
|
|
case STATE_CHANGE_INITSHOW:
|
|
case STATE_CHANGE_CONTROL_FOCUS:
|
|
break;
|
|
//stuff that does invalidate the layout
|
|
default:
|
|
queue_resize();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::DataChanged( const DataChangedEvent& )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplNotifyKeyMouseCommandEventListeners( NotifyEvent& rNEvt )
|
|
{
|
|
if( rNEvt.GetType() == EVENT_COMMAND )
|
|
{
|
|
const CommandEvent* pCEvt = rNEvt.GetCommandEvent();
|
|
if ( pCEvt->GetCommand() != COMMAND_CONTEXTMENU )
|
|
// non context menu events are not to be notified up the chain
|
|
// so we return immediately
|
|
return;
|
|
|
|
if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
|
|
{
|
|
if ( rNEvt.GetWindow() == this )
|
|
// not interested in: The event listeners are already called in ::Command,
|
|
// and calling them here a second time doesn't make sense
|
|
;
|
|
else
|
|
{
|
|
CommandEvent aCommandEvent = ImplTranslateCommandEvent( *pCEvt, rNEvt.GetWindow(), this );
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_COMMAND, &aCommandEvent );
|
|
}
|
|
}
|
|
}
|
|
|
|
// #82968# notify event listeners for mouse and key events seperately and
|
|
// not in PreNotify ( as for focus listeners )
|
|
// this allows for procesing those events internally first and pass it to
|
|
// the toolkit later
|
|
|
|
ImplDelData aDelData;
|
|
ImplAddDel( &aDelData );
|
|
|
|
if( rNEvt.GetType() == EVENT_MOUSEMOVE )
|
|
{
|
|
if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
|
|
{
|
|
if ( rNEvt.GetWindow() == this )
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEMOVE, (void*)rNEvt.GetMouseEvent() );
|
|
else
|
|
{
|
|
MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEMOVE, &aMouseEvent );
|
|
}
|
|
}
|
|
}
|
|
else if( rNEvt.GetType() == EVENT_MOUSEBUTTONUP )
|
|
{
|
|
if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
|
|
{
|
|
if ( rNEvt.GetWindow() == this )
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, (void*)rNEvt.GetMouseEvent() );
|
|
else
|
|
{
|
|
MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONUP, &aMouseEvent );
|
|
}
|
|
}
|
|
}
|
|
else if( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
|
|
{
|
|
if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
|
|
{
|
|
if ( rNEvt.GetWindow() == this )
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, (void*)rNEvt.GetMouseEvent() );
|
|
else
|
|
{
|
|
MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_MOUSEBUTTONDOWN, &aMouseEvent );
|
|
}
|
|
}
|
|
}
|
|
else if( rNEvt.GetType() == EVENT_KEYINPUT )
|
|
{
|
|
if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_KEYINPUT, (void*)rNEvt.GetKeyEvent() );
|
|
}
|
|
else if( rNEvt.GetType() == EVENT_KEYUP )
|
|
{
|
|
if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_KEYUP, (void*)rNEvt.GetKeyEvent() );
|
|
}
|
|
|
|
if ( aDelData.IsDead() )
|
|
return;
|
|
ImplRemoveDel( &aDelData );
|
|
|
|
// #106721# check if we're part of a compound control and notify
|
|
Window *pParent = ImplGetParent();
|
|
while( pParent )
|
|
{
|
|
if( pParent->IsCompoundControl() )
|
|
{
|
|
pParent->ImplNotifyKeyMouseCommandEventListeners( rNEvt );
|
|
break;
|
|
}
|
|
pParent = pParent->ImplGetParent();
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
long Window::PreNotify( NotifyEvent& rNEvt )
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
long bDone = sal_False;
|
|
if ( mpWindowImpl->mpParent && !ImplIsOverlapWindow() )
|
|
bDone = mpWindowImpl->mpParent->PreNotify( rNEvt );
|
|
|
|
if ( !bDone )
|
|
{
|
|
if( rNEvt.GetType() == EVENT_GETFOCUS )
|
|
{
|
|
sal_Bool bCompoundFocusChanged = sal_False;
|
|
if ( mpWindowImpl->mbCompoundControl && !mpWindowImpl->mbCompoundControlHasFocus && HasChildPathFocus() )
|
|
{
|
|
mpWindowImpl->mbCompoundControlHasFocus = sal_True;
|
|
bCompoundFocusChanged = sal_True;
|
|
}
|
|
|
|
if ( bCompoundFocusChanged || ( rNEvt.GetWindow() == this ) )
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_GETFOCUS );
|
|
}
|
|
else if( rNEvt.GetType() == EVENT_LOSEFOCUS )
|
|
{
|
|
sal_Bool bCompoundFocusChanged = sal_False;
|
|
if ( mpWindowImpl->mbCompoundControl && mpWindowImpl->mbCompoundControlHasFocus && !HasChildPathFocus() )
|
|
{
|
|
mpWindowImpl->mbCompoundControlHasFocus = sal_False ;
|
|
bCompoundFocusChanged = sal_True;
|
|
}
|
|
|
|
if ( bCompoundFocusChanged || ( rNEvt.GetWindow() == this ) )
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_LOSEFOCUS );
|
|
}
|
|
|
|
// #82968# mouse and key events will be notified after processing ( in ImplNotifyKeyMouseCommandEventListeners() )!
|
|
// see also ImplHandleMouseEvent(), ImplHandleKey()
|
|
|
|
}
|
|
|
|
return bDone;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
long Window::Notify( NotifyEvent& rNEvt )
|
|
{
|
|
{ // Parentheses, as in this handler the window can be destroyed
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
}
|
|
|
|
long nRet = sal_False;
|
|
|
|
// check for docking window
|
|
// but do nothing if window is docked and locked
|
|
ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
|
|
if( pWrapper && !( !pWrapper->IsFloatingMode() && pWrapper->IsLocked() ) )
|
|
{
|
|
if ( rNEvt.GetType() == EVENT_MOUSEBUTTONDOWN )
|
|
{
|
|
const MouseEvent* pMEvt = rNEvt.GetMouseEvent();
|
|
sal_Bool bHit = pWrapper->GetDragArea().IsInside( pMEvt->GetPosPixel() );
|
|
if ( pMEvt->IsLeft() )
|
|
{
|
|
if ( pMEvt->IsMod1() && (pMEvt->GetClicks() == 2) )
|
|
{
|
|
// ctrl double click toggles floating mode
|
|
pWrapper->SetFloatingMode( !pWrapper->IsFloatingMode() );
|
|
return sal_True;
|
|
}
|
|
else if ( pMEvt->GetClicks() == 1 && bHit)
|
|
{
|
|
// allow start docking during mouse move
|
|
pWrapper->ImplEnableStartDocking();
|
|
return sal_True;
|
|
}
|
|
}
|
|
}
|
|
else if ( rNEvt.GetType() == EVENT_MOUSEMOVE )
|
|
{
|
|
const MouseEvent* pMEvt = rNEvt.GetMouseEvent();
|
|
sal_Bool bHit = pWrapper->GetDragArea().IsInside( pMEvt->GetPosPixel() );
|
|
if ( pMEvt->IsLeft() )
|
|
{
|
|
// check if a single click initiated this sequence ( ImplStartDockingEnabled() )
|
|
// check if window is docked and
|
|
if( pWrapper->ImplStartDockingEnabled() && !pWrapper->IsFloatingMode() &&
|
|
!pWrapper->IsDocking() && bHit )
|
|
{
|
|
Point aPos = pMEvt->GetPosPixel();
|
|
Window* pWindow = rNEvt.GetWindow();
|
|
if ( pWindow != this )
|
|
{
|
|
aPos = pWindow->OutputToScreenPixel( aPos );
|
|
aPos = ScreenToOutputPixel( aPos );
|
|
}
|
|
pWrapper->ImplStartDocking( aPos );
|
|
}
|
|
return sal_True;
|
|
}
|
|
}
|
|
else if( rNEvt.GetType() == EVENT_KEYINPUT )
|
|
{
|
|
const KeyCode& rKey = rNEvt.GetKeyEvent()->GetKeyCode();
|
|
if( rKey.GetCode() == KEY_F10 && rKey.GetModifier() &&
|
|
rKey.IsShift() && rKey.IsMod1() )
|
|
{
|
|
pWrapper->SetFloatingMode( !pWrapper->IsFloatingMode() );
|
|
/* At this point the floating toolbar frame does not have the
|
|
* input focus since these frames don't get the focus per default
|
|
* To enable keyboard handling of this toolbar set the input focus
|
|
* to the frame. This needs to be done with ToTop since GrabFocus
|
|
* would not notice any change since "this" already has the focus.
|
|
*/
|
|
if( pWrapper->IsFloatingMode() )
|
|
ToTop( TOTOP_GRABFOCUSONLY );
|
|
return sal_True;
|
|
}
|
|
}
|
|
}
|
|
|
|
// manage the dialogs
|
|
if ( (GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL )
|
|
{
|
|
// if the parent also has dialog control activated, the parent takes over control
|
|
if ( (rNEvt.GetType() == EVENT_KEYINPUT) || (rNEvt.GetType() == EVENT_KEYUP) )
|
|
{
|
|
if ( ImplIsOverlapWindow() ||
|
|
((getNonLayoutRealParent(this)->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL) )
|
|
{
|
|
nRet = ImplDlgCtrl( *rNEvt.GetKeyEvent(), rNEvt.GetType() == EVENT_KEYINPUT );
|
|
}
|
|
}
|
|
else if ( (rNEvt.GetType() == EVENT_GETFOCUS) || (rNEvt.GetType() == EVENT_LOSEFOCUS) )
|
|
{
|
|
ImplDlgCtrlFocusChanged( rNEvt.GetWindow(), rNEvt.GetType() == EVENT_GETFOCUS );
|
|
if ( (rNEvt.GetWindow() == this) && (rNEvt.GetType() == EVENT_GETFOCUS) &&
|
|
!(GetStyle() & WB_TABSTOP) && !(mpWindowImpl->mnDlgCtrlFlags & WINDOW_DLGCTRL_WANTFOCUS) )
|
|
{
|
|
sal_uInt16 n = 0;
|
|
Window* pFirstChild = ImplGetDlgWindow( n, DLGWINDOW_FIRST );
|
|
if ( pFirstChild )
|
|
pFirstChild->ImplControlFocus();
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( !nRet )
|
|
{
|
|
if ( mpWindowImpl->mpParent && !ImplIsOverlapWindow() )
|
|
nRet = mpWindowImpl->mpParent->Notify( rNEvt );
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCallEventListeners( sal_uLong nEvent, void* pData )
|
|
{
|
|
// The implementation was moved to CallEventListeners(),
|
|
// because derived classes in svtools must be able to
|
|
// call the event listeners and ImplCallEventListeners()
|
|
// is not exported.
|
|
// TODO: replace ImplCallEventListeners() by CallEventListeners() in vcl
|
|
|
|
CallEventListeners( nEvent, pData );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::CallEventListeners( sal_uLong nEvent, void* pData )
|
|
{
|
|
VclWindowEvent aEvent( this, nEvent, pData );
|
|
|
|
ImplDelData aDelData;
|
|
ImplAddDel( &aDelData );
|
|
|
|
ImplGetSVData()->mpApp->ImplCallEventListeners( &aEvent );
|
|
|
|
if ( aDelData.IsDead() )
|
|
return;
|
|
|
|
mpWindowImpl->maEventListeners.Call( &aEvent );
|
|
|
|
if ( aDelData.IsDead() )
|
|
return;
|
|
|
|
ImplRemoveDel( &aDelData );
|
|
|
|
Window* pWindow = this;
|
|
while ( pWindow )
|
|
{
|
|
pWindow->ImplAddDel( &aDelData );
|
|
|
|
pWindow->mpWindowImpl->maChildEventListeners.Call( &aEvent );
|
|
|
|
if ( aDelData.IsDead() )
|
|
return;
|
|
|
|
pWindow->ImplRemoveDel( &aDelData );
|
|
|
|
pWindow = pWindow->GetParent();
|
|
}
|
|
}
|
|
|
|
void Window::FireVclEvent( VclSimpleEvent* pEvent )
|
|
{
|
|
ImplGetSVData()->mpApp->ImplCallEventListeners(pEvent);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::AddEventListener( const Link& rEventListener )
|
|
{
|
|
mpWindowImpl->maEventListeners.addListener( rEventListener );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::RemoveEventListener( const Link& rEventListener )
|
|
{
|
|
mpWindowImpl->maEventListeners.removeListener( rEventListener );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::AddChildEventListener( const Link& rEventListener )
|
|
{
|
|
mpWindowImpl->maChildEventListeners.addListener( rEventListener );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::RemoveChildEventListener( const Link& rEventListener )
|
|
{
|
|
mpWindowImpl->maChildEventListeners.removeListener( rEventListener );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_uLong Window::PostUserEvent( const Link& rLink, void* pCaller )
|
|
{
|
|
sal_uLong nEventId;
|
|
PostUserEvent( nEventId, rLink, pCaller );
|
|
return nEventId;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::PostUserEvent( sal_uLong& rEventId, const Link& rLink, void* pCaller )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplSVEvent* pSVEvent = new ImplSVEvent;
|
|
pSVEvent->mnEvent = 0;
|
|
pSVEvent->mpData = pCaller;
|
|
pSVEvent->mpLink = new Link( rLink );
|
|
pSVEvent->mpWindow = this;
|
|
pSVEvent->mbCall = sal_True;
|
|
ImplAddDel( &(pSVEvent->maDelData) );
|
|
rEventId = (sal_uLong)pSVEvent;
|
|
if ( mpWindowImpl->mpFrame->PostEvent( pSVEvent ) )
|
|
return sal_True;
|
|
else
|
|
{
|
|
rEventId = 0;
|
|
ImplRemoveDel( &(pSVEvent->maDelData) );
|
|
delete pSVEvent;
|
|
return sal_False;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::RemoveUserEvent( sal_uLong nUserEvent )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplSVEvent* pSVEvent = (ImplSVEvent*)nUserEvent;
|
|
|
|
DBG_ASSERT( pSVEvent->mpWindow == this,
|
|
"Window::RemoveUserEvent(): Event doesn't send to this window or is already removed" );
|
|
DBG_ASSERT( pSVEvent->mbCall,
|
|
"Window::RemoveUserEvent(): Event is already removed" );
|
|
|
|
if ( pSVEvent->mpWindow )
|
|
{
|
|
pSVEvent->mpWindow->ImplRemoveDel( &(pSVEvent->maDelData) );
|
|
pSVEvent->mpWindow = NULL;
|
|
}
|
|
|
|
pSVEvent->mbCall = sal_False;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::IsLocked( sal_Bool bChildren ) const
|
|
{
|
|
if ( mpWindowImpl->mnLockCount != 0 )
|
|
return sal_True;
|
|
|
|
if ( bChildren || mpWindowImpl->mbChildNotify )
|
|
{
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
if ( pChild->IsLocked( sal_True ) )
|
|
return sal_True;
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
return sal_False;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetStyle( WinBits nStyle )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mnStyle != nStyle )
|
|
{
|
|
mpWindowImpl->mnPrevStyle = mpWindowImpl->mnStyle;
|
|
mpWindowImpl->mnStyle = nStyle;
|
|
StateChanged( STATE_CHANGE_STYLE );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetExtendedStyle( WinBits nExtendedStyle )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mnExtendedStyle != nExtendedStyle )
|
|
{
|
|
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;
|
|
StateChanged( STATE_CHANGE_EXTENDEDSTYLE );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
SystemWindow* Window::GetSystemWindow() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
const Window* pWin = this;
|
|
while ( pWin && !pWin->IsSystemWindow() )
|
|
pWin = pWin->GetParent();
|
|
return (SystemWindow*)pWin;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetBorderStyle( sal_uInt16 nBorderStyle )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
if( nBorderStyle == WINDOW_BORDER_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
|
|
Window* pBorderWin = mpWindowImpl->mpBorderWindow;
|
|
// remove us as border window's client
|
|
pBorderWin->mpWindowImpl->mpClientWindow = NULL;
|
|
mpWindowImpl->mpBorderWindow = NULL;
|
|
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
|
|
delete pBorderWin;
|
|
|
|
// set new style bits
|
|
SetStyle( GetStyle() & (~WB_BORDER) );
|
|
}
|
|
else
|
|
{
|
|
if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
|
|
((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetBorderStyle( nBorderStyle );
|
|
else
|
|
mpWindowImpl->mpBorderWindow->SetBorderStyle( nBorderStyle );
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_uInt16 Window::GetBorderStyle() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
|
|
return ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->GetBorderStyle();
|
|
else
|
|
return mpWindowImpl->mpBorderWindow->GetBorderStyle();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
long Window::CalcTitleWidth() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
if ( mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW )
|
|
return ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->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();
|
|
Font aFont = GetFont();
|
|
((Window*)this)->SetPointFont( rStyleSettings.GetTitleFont() );
|
|
long nTitleWidth = GetTextWidth( GetText() );
|
|
((Window*)this)->SetFont( aFont );
|
|
nTitleWidth += rStyleSettings.GetTitleHeight() * 3;
|
|
nTitleWidth += rStyleSettings.GetBorderSize() * 2;
|
|
nTitleWidth += 10;
|
|
return nTitleWidth;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::EnableClipSiblings( sal_Bool bClipSiblings )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->EnableClipSiblings( bClipSiblings );
|
|
|
|
mpWindowImpl->mbClipSiblings = bClipSiblings;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetMouseTransparent( sal_Bool bTransparent )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->SetMouseTransparent( bTransparent );
|
|
|
|
if( mpWindowImpl->mpSysObj )
|
|
mpWindowImpl->mpSysObj->SetMouseTransparent( bTransparent );
|
|
|
|
mpWindowImpl->mbMouseTransparent = bTransparent;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetPaintTransparent( sal_Bool bTransparent )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
// transparency is not useful for frames as the background would have to be provided by a different frame
|
|
if( bTransparent && mpWindowImpl->mbFrame )
|
|
return;
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->SetPaintTransparent( bTransparent );
|
|
|
|
mpWindowImpl->mbPaintTransparent = bTransparent;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetInputContext( const InputContext& rInputContext )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
mpWindowImpl->maInputContext = rInputContext;
|
|
if ( !mpWindowImpl->mbInFocusHdl && HasFocus() )
|
|
ImplNewInputContext();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::EndExtTextInput( sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mbExtTextInput )
|
|
ImplGetFrame()->EndExtTextInput( nFlags );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetCursorRect( const Rectangle* pRect, long nExtTextInputWidth )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplWinData* pWinData = ImplGetWinData();
|
|
if ( pWinData->mpCursorRect )
|
|
{
|
|
if ( pRect )
|
|
*pWinData->mpCursorRect = *pRect;
|
|
else
|
|
{
|
|
delete pWinData->mpCursorRect;
|
|
pWinData->mpCursorRect = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pRect )
|
|
pWinData->mpCursorRect = new Rectangle( *pRect );
|
|
}
|
|
|
|
pWinData->mnCursorExtWidth = nExtTextInputWidth;
|
|
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
const Rectangle* Window::GetCursorRect() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplWinData* pWinData = ImplGetWinData();
|
|
return pWinData->mpCursorRect;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
long Window::GetCursorExtTextInputWidth() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplWinData* pWinData = ImplGetWinData();
|
|
return pWinData->mnCursorExtWidth;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
void Window::SetSettings( const AllSettings& rSettings )
|
|
{
|
|
SetSettings( rSettings, sal_False );
|
|
}
|
|
|
|
void Window::SetSettings( const AllSettings& rSettings, sal_Bool bChild )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
mpWindowImpl->mpBorderWindow->SetSettings( rSettings, sal_False );
|
|
if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
|
|
((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow )
|
|
((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow->SetSettings( rSettings, sal_True );
|
|
}
|
|
|
|
AllSettings aOldSettings = maSettings;
|
|
OutputDevice::SetSettings( rSettings );
|
|
sal_uLong nChangeFlags = aOldSettings.GetChangeFlags( rSettings );
|
|
|
|
// recalculate AppFont-resolution and DPI-resolution
|
|
ImplInitResolutionSettings();
|
|
|
|
if ( nChangeFlags )
|
|
{
|
|
DataChangedEvent aDCEvt( DATACHANGED_SETTINGS, &aOldSettings, nChangeFlags );
|
|
DataChanged( aDCEvt );
|
|
}
|
|
|
|
if ( bChild || mpWindowImpl->mbChildNotify )
|
|
{
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->SetSettings( rSettings, bChild );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::UpdateSettings( const AllSettings& rSettings, sal_Bool bChild )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
mpWindowImpl->mpBorderWindow->UpdateSettings( rSettings, sal_False );
|
|
if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
|
|
((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow )
|
|
((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow->UpdateSettings( rSettings, sal_True );
|
|
}
|
|
|
|
AllSettings aOldSettings = maSettings;
|
|
sal_uLong nChangeFlags = maSettings.Update( maSettings.GetWindowUpdate(), rSettings );
|
|
nChangeFlags |= SETTINGS_IN_UPDATE_SETTINGS; // Set this flag so the receiver of the data changed
|
|
// event can distinguish between the changing of global
|
|
// setting and a local change ( with SetSettings )
|
|
|
|
// recalculate AppFont-resolution and DPI-resolution
|
|
ImplInitResolutionSettings();
|
|
|
|
/* #i73785#
|
|
* do not overwrite a WheelBehavior with false
|
|
* this looks kind of a hack, but WheelBehavior
|
|
* is always a local change, not a system property,
|
|
* so we can spare all our users the hassle of reacting on
|
|
* this in their respective DataChanged.
|
|
*/
|
|
MouseSettings aSet( maSettings.GetMouseSettings() );
|
|
aSet.SetWheelBehavior( aOldSettings.GetMouseSettings().GetWheelBehavior() );
|
|
maSettings.SetMouseSettings( aSet );
|
|
|
|
if( (nChangeFlags & SETTINGS_STYLE) && IsBackground() )
|
|
{
|
|
Wallpaper aWallpaper = GetBackground();
|
|
if( !aWallpaper.IsBitmap() && !aWallpaper.IsGradient() )
|
|
{
|
|
if ( mpWindowImpl->mnStyle & WB_3DLOOK )
|
|
SetBackground( Wallpaper( rSettings.GetStyleSettings().GetFaceColor() ) );
|
|
else
|
|
SetBackground( Wallpaper( rSettings.GetStyleSettings().GetWindowColor() ) );
|
|
}
|
|
}
|
|
|
|
if ( nChangeFlags )
|
|
{
|
|
DataChangedEvent aDCEvt( DATACHANGED_SETTINGS, &aOldSettings, nChangeFlags );
|
|
DataChanged( aDCEvt );
|
|
// notify data change handler
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_DATACHANGED, &aDCEvt);
|
|
}
|
|
|
|
if ( bChild || mpWindowImpl->mbChildNotify )
|
|
{
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->UpdateSettings( rSettings, bChild );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::NotifyAllChildren( DataChangedEvent& rDCEvt )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
DataChanged( rDCEvt );
|
|
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->NotifyAllChildren( rDCEvt );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetPointFont( const Font& rFont )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
Font aFont = rFont;
|
|
ImplPointToLogic( aFont );
|
|
SetFont( aFont );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Font Window::GetPointFont() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
Font aFont = GetFont();
|
|
ImplLogicToPoint( aFont );
|
|
return aFont;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetParentClipMode( sal_uInt16 nMode )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->SetParentClipMode( nMode );
|
|
else
|
|
{
|
|
if ( !ImplIsOverlapWindow() )
|
|
{
|
|
mpWindowImpl->mnParentClipMode = nMode;
|
|
if ( nMode & PARENTCLIPMODE_CLIP )
|
|
mpWindowImpl->mpParent->mpWindowImpl->mbClipChildren = sal_True;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_uInt16 Window::GetParentClipMode() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
return mpWindowImpl->mpBorderWindow->GetParentClipMode();
|
|
else
|
|
return mpWindowImpl->mnParentClipMode;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetWindowRegionPixel()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->SetWindowRegionPixel();
|
|
else if( mpWindowImpl->mbFrame )
|
|
{
|
|
mpWindowImpl->maWinRegion = Region( REGION_NULL);
|
|
mpWindowImpl->mbWinRegion = sal_False;
|
|
mpWindowImpl->mpFrame->ResetClipRegion();
|
|
}
|
|
else
|
|
{
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
{
|
|
mpWindowImpl->maWinRegion = Region( REGION_NULL );
|
|
mpWindowImpl->mbWinRegion = sal_False;
|
|
ImplSetClipFlag();
|
|
|
|
if ( IsReallyVisible() )
|
|
{
|
|
// restore background storage
|
|
if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mpSaveBackDev )
|
|
ImplDeleteOverlapBackground();
|
|
if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
|
|
ImplInvalidateAllOverlapBackgrounds();
|
|
Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
Region aRegion( aRect );
|
|
ImplInvalidateParentFrameRegion( aRegion );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetWindowRegionPixel( const Region& rRegion )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->SetWindowRegionPixel( rRegion );
|
|
else if( mpWindowImpl->mbFrame )
|
|
{
|
|
if( rRegion.GetType() != REGION_NULL )
|
|
{
|
|
mpWindowImpl->maWinRegion = rRegion;
|
|
mpWindowImpl->mbWinRegion = ! rRegion.IsEmpty();
|
|
if( mpWindowImpl->mbWinRegion )
|
|
{
|
|
// set/update ClipRegion
|
|
long nX;
|
|
long nY;
|
|
long nWidth;
|
|
long nHeight;
|
|
sal_uLong nRectCount;
|
|
ImplRegionInfo aInfo;
|
|
sal_Bool bRegionRect;
|
|
|
|
nRectCount = mpWindowImpl->maWinRegion.GetRectCount();
|
|
mpWindowImpl->mpFrame->BeginSetClipRegion( nRectCount );
|
|
bRegionRect = mpWindowImpl->maWinRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
|
|
while ( bRegionRect )
|
|
{
|
|
mpWindowImpl->mpFrame->UnionClipRegion( nX, nY, nWidth, nHeight );
|
|
bRegionRect = mpWindowImpl->maWinRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
|
|
}
|
|
mpWindowImpl->mpFrame->EndSetClipRegion();
|
|
}
|
|
else
|
|
SetWindowRegionPixel();
|
|
}
|
|
else
|
|
SetWindowRegionPixel();
|
|
}
|
|
else
|
|
{
|
|
if ( rRegion.GetType() == REGION_NULL )
|
|
{
|
|
if ( mpWindowImpl->mbWinRegion )
|
|
{
|
|
mpWindowImpl->maWinRegion = Region( REGION_NULL );
|
|
mpWindowImpl->mbWinRegion = sal_False;
|
|
ImplSetClipFlag();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mpWindowImpl->maWinRegion = rRegion;
|
|
mpWindowImpl->mbWinRegion = sal_True;
|
|
ImplSetClipFlag();
|
|
}
|
|
|
|
if ( IsReallyVisible() )
|
|
{
|
|
// restore background storage
|
|
if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mpSaveBackDev )
|
|
ImplDeleteOverlapBackground();
|
|
if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
|
|
ImplInvalidateAllOverlapBackgrounds();
|
|
Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
Region aRegion( aRect );
|
|
ImplInvalidateParentFrameRegion( aRegion );
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
const Region& Window::GetWindowRegionPixel() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
return mpWindowImpl->mpBorderWindow->GetWindowRegionPixel();
|
|
else
|
|
return mpWindowImpl->maWinRegion;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::IsWindowRegionPixel() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
return mpWindowImpl->mpBorderWindow->IsWindowRegionPixel();
|
|
else
|
|
return mpWindowImpl->mbWinRegion;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Region Window::GetWindowClipRegionPixel( sal_uInt16 nFlags ) const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
Region aWinClipRegion;
|
|
|
|
if ( nFlags & WINDOW_GETCLIPREGION_NOCHILDREN )
|
|
{
|
|
if ( mpWindowImpl->mbInitWinClipRegion )
|
|
((Window*)this)->ImplInitWinClipRegion();
|
|
aWinClipRegion = mpWindowImpl->maWinClipRegion;
|
|
}
|
|
else
|
|
{
|
|
Region* pWinChildClipRegion = ((Window*)this)->ImplGetWinChildClipRegion();
|
|
aWinClipRegion = *pWinChildClipRegion;
|
|
// --- RTL --- remirror clip region before passing it to somebody
|
|
if( ImplIsAntiparallel() )
|
|
ImplReMirror( aWinClipRegion );
|
|
}
|
|
|
|
if ( nFlags & WINDOW_GETCLIPREGION_NULL )
|
|
{
|
|
Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
Region aWinRegion( aWinRect );
|
|
|
|
if ( aWinRegion == aWinClipRegion )
|
|
aWinClipRegion.SetNull();
|
|
}
|
|
|
|
aWinClipRegion.Move( -mnOutOffX, -mnOutOffY );
|
|
|
|
return aWinClipRegion;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Region Window::GetPaintRegion() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpPaintRegion )
|
|
{
|
|
Region aRegion = *mpWindowImpl->mpPaintRegion;
|
|
aRegion.Move( -mnOutOffX, -mnOutOffY );
|
|
return PixelToLogic( aRegion );
|
|
}
|
|
else
|
|
{
|
|
Region aPaintRegion( REGION_NULL );
|
|
return aPaintRegion;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ExpandPaintClipRegion( const Region& rRegion )
|
|
{
|
|
if( mpWindowImpl->mpPaintRegion )
|
|
{
|
|
Region aPixRegion = LogicToPixel( rRegion );
|
|
Region aDevPixRegion = ImplPixelToDevicePixel( aPixRegion );
|
|
|
|
Region aWinChildRegion = *ImplGetWinChildClipRegion();
|
|
// --- RTL -- only this region is in frame coordinates, so re-mirror it
|
|
if( ImplIsAntiparallel() )
|
|
ImplReMirror( aWinChildRegion );
|
|
aDevPixRegion.Intersect( aWinChildRegion );
|
|
if( ! aDevPixRegion.IsEmpty() )
|
|
{
|
|
mpWindowImpl->mpPaintRegion->Union( aDevPixRegion );
|
|
mbInitClipRegion = sal_True;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
static SystemWindow *ImplGetLastSystemWindow( Window *pWin )
|
|
{
|
|
// get the most top-level system window, the one that contains the taskpanelist
|
|
SystemWindow *pSysWin = NULL;
|
|
if( !pWin )
|
|
return pSysWin;
|
|
Window *pMyParent = pWin;
|
|
while ( pMyParent )
|
|
{
|
|
if ( pMyParent->IsSystemWindow() )
|
|
pSysWin = (SystemWindow*)pMyParent;
|
|
pMyParent = pMyParent->GetParent();
|
|
}
|
|
return pSysWin;
|
|
}
|
|
|
|
void Window::SetParent( Window* pNewParent )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
DBG_ASSERT( pNewParent, "Window::SetParent(): pParent == NULL" );
|
|
DBG_ASSERT( pNewParent != this, "someone tried to reparent a window to itself" );
|
|
|
|
if( pNewParent == this )
|
|
return;
|
|
|
|
// check if the taskpanelist would change and move the window pointer accordingly
|
|
SystemWindow *pSysWin = ImplGetLastSystemWindow(this);
|
|
SystemWindow *pNewSysWin = NULL;
|
|
sal_Bool bChangeTaskPaneList = sal_False;
|
|
if( pSysWin && pSysWin->ImplIsInTaskPaneList( this ) )
|
|
{
|
|
pNewSysWin = ImplGetLastSystemWindow( pNewParent );
|
|
if( pNewSysWin && pNewSysWin != pSysWin )
|
|
{
|
|
bChangeTaskPaneList = sal_True;
|
|
pSysWin->GetTaskPaneList()->RemoveWindow( this );
|
|
}
|
|
}
|
|
// remove ownerdraw decorated windows from list in the top-most frame window
|
|
if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
|
|
{
|
|
::std::vector< Window* >& rList = ImplGetOwnerDrawList();
|
|
::std::vector< Window* >::iterator p;
|
|
p = ::std::find( rList.begin(), rList.end(), this );
|
|
if( p != rList.end() )
|
|
rList.erase( p );
|
|
}
|
|
|
|
ImplSetFrameParent( pNewParent );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
mpWindowImpl->mpRealParent = pNewParent;
|
|
mpWindowImpl->mpBorderWindow->SetParent( pNewParent );
|
|
return;
|
|
}
|
|
|
|
if ( mpWindowImpl->mpParent == pNewParent )
|
|
return;
|
|
|
|
if ( mpWindowImpl->mbFrame )
|
|
mpWindowImpl->mpFrame->SetParent( pNewParent->mpWindowImpl->mpFrame );
|
|
|
|
sal_Bool bVisible = IsVisible();
|
|
Show( false, SHOW_NOFOCUSCHANGE );
|
|
|
|
// check if the overlap window changes
|
|
Window* pOldOverlapWindow;
|
|
Window* pNewOverlapWindow = NULL;
|
|
if ( ImplIsOverlapWindow() )
|
|
pOldOverlapWindow = NULL;
|
|
else
|
|
{
|
|
pNewOverlapWindow = pNewParent->ImplGetFirstOverlapWindow();
|
|
if ( mpWindowImpl->mpOverlapWindow != pNewOverlapWindow )
|
|
pOldOverlapWindow = mpWindowImpl->mpOverlapWindow;
|
|
else
|
|
pOldOverlapWindow = NULL;
|
|
}
|
|
|
|
// convert windows in the hierarchy
|
|
sal_Bool bFocusOverlapWin = HasChildPathFocus( sal_True );
|
|
sal_Bool bFocusWin = HasChildPathFocus();
|
|
sal_Bool bNewFrame = pNewParent->mpWindowImpl->mpFrameWindow != mpWindowImpl->mpFrameWindow;
|
|
if ( bNewFrame )
|
|
{
|
|
if ( mpWindowImpl->mpFrameData->mpFocusWin )
|
|
{
|
|
if ( IsWindowOrChild( mpWindowImpl->mpFrameData->mpFocusWin ) )
|
|
mpWindowImpl->mpFrameData->mpFocusWin = NULL;
|
|
}
|
|
if ( mpWindowImpl->mpFrameData->mpMouseMoveWin )
|
|
{
|
|
if ( IsWindowOrChild( mpWindowImpl->mpFrameData->mpMouseMoveWin ) )
|
|
mpWindowImpl->mpFrameData->mpMouseMoveWin = NULL;
|
|
}
|
|
if ( mpWindowImpl->mpFrameData->mpMouseDownWin )
|
|
{
|
|
if ( IsWindowOrChild( mpWindowImpl->mpFrameData->mpMouseDownWin ) )
|
|
mpWindowImpl->mpFrameData->mpMouseDownWin = NULL;
|
|
}
|
|
}
|
|
ImplRemoveWindow( bNewFrame );
|
|
ImplInsertWindow( pNewParent );
|
|
if ( mpWindowImpl->mnParentClipMode & PARENTCLIPMODE_CLIP )
|
|
pNewParent->mpWindowImpl->mbClipChildren = sal_True;
|
|
ImplUpdateWindowPtr();
|
|
if ( ImplUpdatePos() )
|
|
ImplUpdateSysObjPos();
|
|
|
|
// If the Overlap-Window has changed, we need to test whether
|
|
// OverlapWindows that had the Child window as their parent
|
|
// need to be put into the window hierarchy.
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
if ( bNewFrame )
|
|
{
|
|
Window* pOverlapWindow = mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow )
|
|
{
|
|
Window* pNextOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
|
|
pOverlapWindow = pNextOverlapWindow;
|
|
}
|
|
}
|
|
}
|
|
else if ( pOldOverlapWindow )
|
|
{
|
|
// reset Focus-Save
|
|
if ( bFocusWin ||
|
|
(pOldOverlapWindow->mpWindowImpl->mpLastFocusWindow &&
|
|
IsWindowOrChild( pOldOverlapWindow->mpWindowImpl->mpLastFocusWindow )) )
|
|
pOldOverlapWindow->mpWindowImpl->mpLastFocusWindow = NULL;
|
|
|
|
Window* pOverlapWindow = pOldOverlapWindow->mpWindowImpl->mpFirstOverlap;
|
|
while ( pOverlapWindow )
|
|
{
|
|
Window* pNextOverlapWindow = pOverlapWindow->mpWindowImpl->mpNext;
|
|
if ( ImplIsRealParentPath( pOverlapWindow->ImplGetWindow() ) )
|
|
pOverlapWindow->ImplUpdateOverlapWindowPtr( bNewFrame );
|
|
pOverlapWindow = pNextOverlapWindow;
|
|
}
|
|
|
|
// update activate-status at next overlap window
|
|
if ( HasChildPathFocus( sal_True ) )
|
|
ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow );
|
|
}
|
|
|
|
// also convert Activate-Status
|
|
if ( bNewFrame )
|
|
{
|
|
if ( (GetType() == WINDOW_BORDERWINDOW) &&
|
|
(ImplGetWindow()->GetType() == WINDOW_FLOATINGWINDOW) )
|
|
((ImplBorderWindow*)this)->SetDisplayActive( mpWindowImpl->mpFrameData->mbHasFocus );
|
|
}
|
|
|
|
// when required give focus to new frame if
|
|
// FocusWindow is changed with SetParent()
|
|
if ( bFocusOverlapWin )
|
|
{
|
|
mpWindowImpl->mpFrameData->mpFocusWin = Application::GetFocusWindow();
|
|
if ( !mpWindowImpl->mpFrameData->mbHasFocus )
|
|
{
|
|
mpWindowImpl->mpFrame->ToTop( 0 );
|
|
}
|
|
}
|
|
|
|
// Assure DragSource and DropTarget members are created
|
|
if ( bNewFrame )
|
|
{
|
|
GetDropTarget();
|
|
}
|
|
|
|
if( bChangeTaskPaneList )
|
|
pNewSysWin->GetTaskPaneList()->AddWindow( this );
|
|
|
|
if( (GetStyle() & WB_OWNERDRAWDECORATION) && mpWindowImpl->mbFrame )
|
|
ImplGetOwnerDrawList().push_back( this );
|
|
|
|
if ( bVisible )
|
|
Show( true, SHOW_NOFOCUSCHANGE | SHOW_NOACTIVATE );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Show( sal_Bool bVisible, sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mbVisible == bVisible )
|
|
return;
|
|
|
|
ImplDelData aDogTag( this );
|
|
|
|
sal_Bool bRealVisibilityChanged = sal_False;
|
|
mpWindowImpl->mbVisible = (bVisible != 0);
|
|
|
|
if ( !bVisible )
|
|
{
|
|
ImplHideAllOverlaps();
|
|
if( aDogTag.IsDead() )
|
|
return;
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
bool bOldUpdate = mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate;
|
|
if ( mpWindowImpl->mbNoParentUpdate )
|
|
mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = sal_True;
|
|
mpWindowImpl->mpBorderWindow->Show( false, nFlags );
|
|
mpWindowImpl->mpBorderWindow->mpWindowImpl->mbNoParentUpdate = bOldUpdate;
|
|
}
|
|
else if ( mpWindowImpl->mbFrame )
|
|
{
|
|
mpWindowImpl->mbSuppressAccessibilityEvents = sal_True;
|
|
mpWindowImpl->mpFrame->Show( sal_False, sal_False );
|
|
}
|
|
|
|
StateChanged( STATE_CHANGE_VISIBLE );
|
|
|
|
if ( mpWindowImpl->mbReallyVisible )
|
|
{
|
|
Region aInvRegion( REGION_EMPTY );
|
|
sal_Bool bSaveBack = sal_False;
|
|
|
|
if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
|
|
{
|
|
if ( ImplRestoreOverlapBackground( aInvRegion ) )
|
|
bSaveBack = sal_True;
|
|
}
|
|
|
|
if ( !bSaveBack )
|
|
{
|
|
if ( mpWindowImpl->mbInitWinClipRegion )
|
|
ImplInitWinClipRegion();
|
|
aInvRegion = mpWindowImpl->maWinClipRegion;
|
|
}
|
|
|
|
if( aDogTag.IsDead() )
|
|
return;
|
|
|
|
bRealVisibilityChanged = mpWindowImpl->mbReallyVisible;
|
|
ImplResetReallyVisible();
|
|
ImplSetClipFlag();
|
|
|
|
if ( ImplIsOverlapWindow() && !mpWindowImpl->mbFrame )
|
|
{
|
|
// convert focus
|
|
if ( !(nFlags & SHOW_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 & SHOW_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();
|
|
}
|
|
|
|
StateChanged( STATE_CHANGE_VISIBLE );
|
|
|
|
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 & SHOW_NOACTIVATE) )
|
|
{
|
|
ImplStartToTop(( nFlags & SHOW_FOREGROUNDTASK ) ? TOTOP_FOREGROUNDTASK : 0 );
|
|
ImplFocusToTop( 0, sal_False );
|
|
}
|
|
|
|
// save background
|
|
if ( mpWindowImpl->mpOverlapData && mpWindowImpl->mpOverlapData->mbSaveBack )
|
|
ImplSaveOverlapBackground();
|
|
// adjust mpWindowImpl->mbReallyVisible
|
|
bRealVisibilityChanged = !mpWindowImpl->mbReallyVisible;
|
|
ImplSetReallyVisible();
|
|
|
|
// assure clip rectangles will be recalculated
|
|
ImplSetClipFlag();
|
|
|
|
if ( !mpWindowImpl->mbFrame )
|
|
{
|
|
sal_uInt16 nInvalidateFlags = INVALIDATE_CHILDREN;
|
|
if( ! IsPaintTransparent() )
|
|
nInvalidateFlags |= INVALIDATE_NOTRANSPARENT;
|
|
ImplInvalidate( NULL, 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 slot:5500)
|
|
pSVData->mpIntroWindow->Hide();
|
|
}
|
|
|
|
//DBG_ASSERT( !mpWindowImpl->mbSuppressAccessibilityEvents, "Window::Show() - Frame reactivated");
|
|
mpWindowImpl->mbSuppressAccessibilityEvents = sal_False;
|
|
|
|
mpWindowImpl->mbPaintFrame = sal_True;
|
|
sal_Bool bNoActivate = (nFlags & (SHOW_NOACTIVATE|SHOW_NOFOCUSCHANGE)) ? sal_True : sal_False;
|
|
mpWindowImpl->mpFrame->Show( sal_True, bNoActivate );
|
|
if( aDogTag.IsDead() )
|
|
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( aDogTag.IsDead() )
|
|
return;
|
|
|
|
#if OSL_DEBUG_LEVEL > 0
|
|
if ( IsDialog() || (GetType() == WINDOW_TABPAGE) || (GetType() == WINDOW_DOCKINGWINDOW) )
|
|
{
|
|
DBG_DIALOGTEST( this );
|
|
}
|
|
#endif
|
|
|
|
ImplShowAllOverlaps();
|
|
}
|
|
|
|
if( aDogTag.IsDead() )
|
|
return;
|
|
// invalidate all saved backgrounds
|
|
if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
|
|
ImplInvalidateAllOverlapBackgrounds();
|
|
|
|
// 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 )
|
|
ImplCallEventListeners( mpWindowImpl->mbVisible ? VCLEVENT_WINDOW_SHOW : VCLEVENT_WINDOW_HIDE, NULL );
|
|
if( aDogTag.IsDead() )
|
|
return;
|
|
|
|
// #107575#, if a floating windows is shown that grabs the focus, we have to notify the toolkit about it
|
|
// ImplGrabFocus() is not called in this case
|
|
// Because this might lead to problems the task will be shifted to 6.y
|
|
// Note: top-level context menus are registered at the access bridge after being shown,
|
|
// so this will probably not help here....
|
|
/*
|
|
if( mpWindowImpl->mbFloatWin && ((FloatingWindow*) this )->GrabsFocus() )
|
|
{
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
if( !mpWindowImpl->mbVisible )
|
|
{
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_LOSEFOCUS );
|
|
if( pSVData->maWinData.mpFocusWin )
|
|
pSVData->maWinData.mpFocusWin->ImplCallEventListeners( VCLEVENT_WINDOW_GETFOCUS );
|
|
}
|
|
else
|
|
{
|
|
if( pSVData->maWinData.mpFocusWin )
|
|
pSVData->maWinData.mpFocusWin->ImplCallEventListeners( VCLEVENT_WINDOW_LOSEFOCUS );
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_GETFOCUS );
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
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->maResizeTimer.IsActive() )
|
|
{
|
|
ImplDelData aDogtag( this );
|
|
mpWindowImpl->mpFrameData->maResizeTimer.Stop();
|
|
mpWindowImpl->mpFrameData->maResizeTimer.GetTimeoutHdl().Call( NULL );
|
|
if( aDogtag.IsDead() )
|
|
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 )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( !bEnable )
|
|
{
|
|
// the tracking mode will be stopped or the capture will be stolen
|
|
// when a window is disabled,
|
|
if ( IsTracking() )
|
|
EndTracking( ENDTRACK_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, sal_False );
|
|
if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
|
|
((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow )
|
|
((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow->Enable( bEnable, sal_True );
|
|
}
|
|
|
|
// #i56102# restore app focus win in case the
|
|
// window was disabled when the frame focus changed
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
if( bEnable &&
|
|
pSVData->maWinData.mpFocusWin == NULL &&
|
|
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 );
|
|
StateChanged( STATE_CHANGE_ENABLE );
|
|
|
|
ImplCallEventListeners( bEnable ? VCLEVENT_WINDOW_ENABLED : VCLEVENT_WINDOW_DISABLED );
|
|
}
|
|
|
|
if ( bChild || mpWindowImpl->mbChildNotify )
|
|
{
|
|
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 ? sal_True : sal_False;
|
|
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->SetCallHandlersOnInputDisabled( bCall );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
bool Window::IsCallHandlersOnInputDisabled() const
|
|
{
|
|
return mpWindowImpl->mbCallHandlersDuringInputDisabled ? true : false;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::EnableInput( sal_Bool bEnable, sal_Bool bChild )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
sal_Bool bNotify = (bEnable != mpWindowImpl->mbInputDisabled);
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
mpWindowImpl->mpBorderWindow->EnableInput( bEnable, sal_False );
|
|
if ( (mpWindowImpl->mpBorderWindow->GetType() == WINDOW_BORDERWINDOW) &&
|
|
((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow )
|
|
((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->mpMenuBarWindow->EnableInput( bEnable, sal_True );
|
|
}
|
|
|
|
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( ENDTRACK_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 == NULL &&
|
|
mpWindowImpl->mpFrameData->mbHasFocus &&
|
|
mpWindowImpl->mpFrameData->mpFocusWin == this )
|
|
pSVData->maWinData.mpFocusWin = this;
|
|
|
|
if ( bChild || mpWindowImpl->mbChildNotify )
|
|
{
|
|
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 ? EVENT_INPUTENABLE : EVENT_INPUTDISABLE, this );
|
|
Notify( aNEvt );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::EnableInput( sal_Bool bEnable, sal_Bool bChild, sal_Bool bSysWin,
|
|
const Window* pExcludeWindow )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
EnableInput( bEnable, bChild );
|
|
if ( bSysWin )
|
|
{
|
|
// pExculeWindow 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();
|
|
Window* pSysWin = mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mpFirstOverlap;
|
|
while ( pSysWin )
|
|
{
|
|
// Is Window in the path from this window
|
|
if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pSysWin, sal_True ) )
|
|
{
|
|
// Is Window not in the exclude window path or not the
|
|
// exclude window, than change the status
|
|
if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pSysWin, sal_True ) )
|
|
pSysWin->EnableInput( bEnable, bChild );
|
|
}
|
|
pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
|
|
}
|
|
|
|
// enable/disable floating system windows as well
|
|
Window* pFrameWin = ImplGetSVData()->maWinData.mpFirstFrame;
|
|
while ( pFrameWin )
|
|
{
|
|
if( pFrameWin->ImplIsFloatingWindow() )
|
|
{
|
|
// Is Window in the path from this window
|
|
if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( pFrameWin, sal_True ) )
|
|
{
|
|
// Is Window not in the exclude window path or not the
|
|
// exclude window, than change the status
|
|
if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( pFrameWin, sal_True ) )
|
|
pFrameWin->EnableInput( bEnable, bChild );
|
|
}
|
|
}
|
|
pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
|
|
}
|
|
|
|
// the same for ownerdraw floating windows
|
|
if( mpWindowImpl->mbFrame )
|
|
{
|
|
::std::vector< Window* >& rList = mpWindowImpl->mpFrameData->maOwnerDrawList;
|
|
::std::vector< Window* >::iterator p = rList.begin();
|
|
while( p != rList.end() )
|
|
{
|
|
// Is Window in the path from this window
|
|
if ( ImplGetFirstOverlapWindow()->ImplIsWindowOrChild( (*p), sal_True ) )
|
|
{
|
|
// Is Window not in the exclude window path or not the
|
|
// exclude window, than change the status
|
|
if ( !pExcludeWindow || !pExcludeWindow->ImplIsWindowOrChild( (*p), sal_True ) )
|
|
(*p)->EnableInput( bEnable, bChild );
|
|
}
|
|
++p;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::AlwaysEnableInput( sal_Bool bAlways, sal_Bool bChild )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->AlwaysEnableInput( bAlways, sal_False );
|
|
|
|
if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputEnabled )
|
|
{
|
|
mpWindowImpl->meAlwaysInputMode = AlwaysInputEnabled;
|
|
|
|
if ( bAlways )
|
|
EnableInput( sal_True, sal_False );
|
|
}
|
|
else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputEnabled )
|
|
{
|
|
mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
|
|
}
|
|
|
|
if ( bChild || mpWindowImpl->mbChildNotify )
|
|
{
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->AlwaysEnableInput( bAlways, bChild );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::AlwaysDisableInput( sal_Bool bAlways, sal_Bool bChild )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->AlwaysDisableInput( bAlways, sal_False );
|
|
|
|
if( bAlways && mpWindowImpl->meAlwaysInputMode != AlwaysInputDisabled )
|
|
{
|
|
mpWindowImpl->meAlwaysInputMode = AlwaysInputDisabled;
|
|
|
|
if ( bAlways )
|
|
EnableInput( sal_False, sal_False );
|
|
}
|
|
else if( ! bAlways && mpWindowImpl->meAlwaysInputMode == AlwaysInputDisabled )
|
|
{
|
|
mpWindowImpl->meAlwaysInputMode = AlwaysInputNone;
|
|
}
|
|
|
|
if ( bChild || mpWindowImpl->mbChildNotify )
|
|
{
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
pChild->AlwaysDisableInput( bAlways, bChild );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetActivateMode( sal_uInt16 nMode )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->SetActivateMode( nMode );
|
|
|
|
if ( mpWindowImpl->mnActivateMode != nMode )
|
|
{
|
|
mpWindowImpl->mnActivateMode = nMode;
|
|
|
|
// possibly trigger Decativate/Activate
|
|
if ( mpWindowImpl->mnActivateMode )
|
|
{
|
|
if ( (mpWindowImpl->mbActive || (GetType() == WINDOW_BORDERWINDOW)) &&
|
|
!HasChildPathFocus( sal_True ) )
|
|
{
|
|
mpWindowImpl->mbActive = sal_False;
|
|
Deactivate();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !mpWindowImpl->mbActive || (GetType() == WINDOW_BORDERWINDOW) )
|
|
{
|
|
mpWindowImpl->mbActive = sal_True;
|
|
Activate();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ToTop( sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplStartToTop( nFlags );
|
|
ImplFocusToTop( nFlags, IsReallyVisible() );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetZOrder( Window* pRefWindow, sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
mpWindowImpl->mpBorderWindow->SetZOrder( pRefWindow, nFlags );
|
|
return;
|
|
}
|
|
|
|
if ( nFlags & WINDOW_ZORDER_FIRST )
|
|
{
|
|
if ( ImplIsOverlapWindow() )
|
|
pRefWindow = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
|
|
else
|
|
pRefWindow = mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild;
|
|
nFlags |= WINDOW_ZORDER_BEFOR;
|
|
}
|
|
else if ( nFlags & WINDOW_ZORDER_LAST )
|
|
{
|
|
if ( ImplIsOverlapWindow() )
|
|
pRefWindow = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap;
|
|
else
|
|
pRefWindow = mpWindowImpl->mpParent->mpWindowImpl->mpLastChild;
|
|
nFlags |= WINDOW_ZORDER_BEHIND;
|
|
}
|
|
|
|
while ( pRefWindow->mpWindowImpl->mpBorderWindow )
|
|
pRefWindow = pRefWindow->mpWindowImpl->mpBorderWindow;
|
|
if ( (pRefWindow == this) || mpWindowImpl->mbFrame )
|
|
return;
|
|
|
|
DBG_ASSERT( pRefWindow->mpWindowImpl->mpParent == mpWindowImpl->mpParent, "Window::SetZOrder() - pRefWindow has other parent" );
|
|
if ( nFlags & WINDOW_ZORDER_BEFOR )
|
|
{
|
|
if ( pRefWindow->mpWindowImpl->mpPrev == this )
|
|
return;
|
|
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
|
|
if ( !pRefWindow->mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = this;
|
|
}
|
|
else
|
|
{
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = mpWindowImpl->mpPrev;
|
|
if ( !pRefWindow->mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = this;
|
|
}
|
|
|
|
mpWindowImpl->mpPrev = pRefWindow->mpWindowImpl->mpPrev;
|
|
mpWindowImpl->mpNext = pRefWindow;
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = this;
|
|
}
|
|
else if ( nFlags & WINDOW_ZORDER_BEHIND )
|
|
{
|
|
if ( pRefWindow->mpWindowImpl->mpNext == this )
|
|
return;
|
|
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = mpWindowImpl->mpPrev;
|
|
if ( !pRefWindow->mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpLastOverlap = this;
|
|
}
|
|
else
|
|
{
|
|
if ( mpWindowImpl->mpPrev )
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = mpWindowImpl->mpNext;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpFirstChild = mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = mpWindowImpl->mpPrev;
|
|
else
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = mpWindowImpl->mpPrev;
|
|
if ( !pRefWindow->mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpParent->mpWindowImpl->mpLastChild = this;
|
|
}
|
|
|
|
mpWindowImpl->mpPrev = pRefWindow;
|
|
mpWindowImpl->mpNext = pRefWindow->mpWindowImpl->mpNext;
|
|
if ( mpWindowImpl->mpNext )
|
|
mpWindowImpl->mpNext->mpWindowImpl->mpPrev = this;
|
|
mpWindowImpl->mpPrev->mpWindowImpl->mpNext = this;
|
|
}
|
|
|
|
if ( IsReallyVisible() )
|
|
{
|
|
// restore background storage
|
|
if ( mpWindowImpl->mpFrameData->mpFirstBackWin )
|
|
ImplInvalidateAllOverlapBackgrounds();
|
|
|
|
if ( mpWindowImpl->mbInitWinClipRegion || !mpWindowImpl->maWinClipRegion.IsEmpty() )
|
|
{
|
|
sal_Bool bInitWinClipRegion = mpWindowImpl->mbInitWinClipRegion;
|
|
ImplSetClipFlag();
|
|
|
|
// When ClipRegion was not initialised, assume
|
|
// the window has not been sent, therefore do not
|
|
// trigger any Invalidates. This is an optimisation
|
|
// for HTML documents with many controls. If this
|
|
// check gives problems, a flag should be introduced
|
|
// which tracks whether the window has already been
|
|
// emitted after Show
|
|
if ( !bInitWinClipRegion )
|
|
{
|
|
// Invalidate all windows which are next to each other
|
|
// Is INCOMPLETE !!!
|
|
Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
Window* pWindow = NULL;
|
|
if ( ImplIsOverlapWindow() )
|
|
{
|
|
if ( mpWindowImpl->mpOverlapWindow )
|
|
pWindow = mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpFirstOverlap;
|
|
}
|
|
else
|
|
pWindow = ImplGetParent()->mpWindowImpl->mpFirstChild;
|
|
// Invalidate all windows in front of us and which are covered by us
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow == this )
|
|
break;
|
|
Rectangle aCompRect( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
|
|
Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
|
|
if ( aWinRect.IsOver( aCompRect ) )
|
|
pWindow->Invalidate( INVALIDATE_CHILDREN | INVALIDATE_NOTRANSPARENT );
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
// If we are covered by a window in the background
|
|
// we should redraw it
|
|
while ( pWindow )
|
|
{
|
|
if ( pWindow != this )
|
|
{
|
|
Rectangle aCompRect( Point( pWindow->mnOutOffX, pWindow->mnOutOffY ),
|
|
Size( pWindow->mnOutWidth, pWindow->mnOutHeight ) );
|
|
if ( aWinRect.IsOver( aCompRect ) )
|
|
{
|
|
Invalidate( INVALIDATE_CHILDREN | INVALIDATE_NOTRANSPARENT );
|
|
break;
|
|
}
|
|
}
|
|
pWindow = pWindow->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::EnableAlwaysOnTop( sal_Bool bEnable )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
mpWindowImpl->mbAlwaysOnTop = bEnable;
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->EnableAlwaysOnTop( bEnable );
|
|
else if ( bEnable && IsReallyVisible() )
|
|
ToTop();
|
|
|
|
if ( mpWindowImpl->mbFrame )
|
|
mpWindowImpl->mpFrame->SetAlwaysOnTop( bEnable );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::setPosSizePixel( long nX, long nY,
|
|
long nWidth, long nHeight, sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
sal_Bool bHasValidSize = !mpWindowImpl->mbDefSize;
|
|
|
|
if ( nFlags & WINDOW_POSSIZE_POS )
|
|
mpWindowImpl->mbDefPos = sal_False;
|
|
if ( nFlags & WINDOW_POSSIZE_SIZE )
|
|
mpWindowImpl->mbDefSize = sal_False;
|
|
|
|
// The top BorderWindow is the window which is to be positioned
|
|
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 & WINDOW_POSSIZE_WIDTH) )
|
|
nWidth = pWindow->mnOutWidth;
|
|
if ( !(nFlags & WINDOW_POSSIZE_HEIGHT) )
|
|
nHeight = pWindow->mnOutHeight;
|
|
|
|
|
|
sal_uInt16 nSysFlags=0;
|
|
if( nFlags & WINDOW_POSSIZE_WIDTH )
|
|
nSysFlags |= SAL_FRAME_POSSIZE_WIDTH;
|
|
if( nFlags & WINDOW_POSSIZE_HEIGHT )
|
|
nSysFlags |= SAL_FRAME_POSSIZE_HEIGHT;
|
|
if( nFlags & WINDOW_POSSIZE_X )
|
|
{
|
|
nSysFlags |= SAL_FRAME_POSSIZE_X;
|
|
if( pWindow->GetParent() && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
|
|
{
|
|
Window* pParent = pWindow->GetParent();
|
|
nX += pParent->mnOutOffX;
|
|
}
|
|
if( GetParent() && GetParent()->ImplIsAntiparallel() )
|
|
{
|
|
// --- RTL --- (re-mirror at parent window)
|
|
Rectangle aRect( Point ( nX, nY ), Size( nWidth, nHeight ) );
|
|
GetParent()->ImplReMirror( aRect );
|
|
nX = aRect.Left();
|
|
}
|
|
}
|
|
if( !(nFlags & WINDOW_POSSIZE_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( pWindow->GetParent() && pWindow->GetParent()->ImplHasMirroredGraphics() )
|
|
{
|
|
long myWidth = nOldWidth;
|
|
if( !myWidth )
|
|
myWidth = mpWindowImpl->mpFrame->GetUnmirroredGeometry().nWidth;
|
|
if( !myWidth )
|
|
myWidth = nWidth;
|
|
nFlags |= WINDOW_POSSIZE_X;
|
|
nSysFlags |= SAL_FRAME_POSSIZE_X;
|
|
nX = mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX - pWindow->GetParent()->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX -
|
|
mpWindowImpl->mpFrame->GetUnmirroredGeometry().nLeftDecoration;
|
|
nX = pWindow->GetParent()->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX - mpWindowImpl->mpFrame->GetUnmirroredGeometry().nLeftDecoration +
|
|
pWindow->GetParent()->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nWidth - myWidth - 1 - mpWindowImpl->mpFrame->GetUnmirroredGeometry().nX;
|
|
if(!(nFlags & WINDOW_POSSIZE_Y))
|
|
{
|
|
nFlags |= WINDOW_POSSIZE_Y;
|
|
nSysFlags |= SAL_FRAME_POSSIZE_Y;
|
|
nY = mpWindowImpl->mpFrame->GetUnmirroredGeometry().nY - pWindow->GetParent()->mpWindowImpl->mpFrame->GetUnmirroredGeometry().nY -
|
|
mpWindowImpl->mpFrame->GetUnmirroredGeometry().nTopDecoration;
|
|
}
|
|
}
|
|
}
|
|
if( nFlags & WINDOW_POSSIZE_Y )
|
|
{
|
|
nSysFlags |= SAL_FRAME_POSSIZE_Y;
|
|
if( pWindow->GetParent() && (pWindow->GetStyle() & WB_SYSTEMCHILDWINDOW) )
|
|
{
|
|
Window* pParent = pWindow->GetParent();
|
|
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 havn'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;
|
|
if( ImplHasMirroredGraphics() )
|
|
{
|
|
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 = ((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 = ((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( Window *pRelativeWindow ) const
|
|
{
|
|
// with decoration
|
|
return ImplGetWindowExtentsRelative( pRelativeWindow, sal_False );
|
|
}
|
|
|
|
Rectangle Window::GetClientWindowExtentsRelative( Window *pRelativeWindow ) const
|
|
{
|
|
// without decoration
|
|
return ImplGetWindowExtentsRelative( pRelativeWindow, sal_True );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Rectangle Window::ImplGetWindowExtentsRelative( Window *pRelativeWindow, sal_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 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
|
|
Window *pRelWin = (!bClientOnly && pRelativeWindow->mpWindowImpl->mpBorderWindow) ? pRelativeWindow->mpWindowImpl->mpBorderWindow : pRelativeWindow;
|
|
aPos = pRelWin->AbsoluteScreenToOutputPixel( aPos );
|
|
}
|
|
return Rectangle( aPos, aSize );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Scroll( long nHorzScroll, long nVertScroll, sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplScroll( Rectangle( Point( mnOutOffX, mnOutOffY ),
|
|
Size( mnOutWidth, mnOutHeight ) ),
|
|
nHorzScroll, nVertScroll, nFlags & ~SCROLL_CLIP );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Scroll( long nHorzScroll, long nVertScroll,
|
|
const Rectangle& rRect, sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
Rectangle aRect = ImplLogicToDevicePixel( rRect );
|
|
aRect.Intersection( Rectangle( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) ) );
|
|
if ( !aRect.IsEmpty() )
|
|
ImplScroll( aRect, nHorzScroll, nVertScroll, nFlags );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Invalidate( sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
|
|
return;
|
|
|
|
ImplInvalidate( NULL, nFlags );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Invalidate( const Rectangle& rRect, sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
|
|
return;
|
|
|
|
Rectangle aRect = ImplLogicToDevicePixel( rRect );
|
|
if ( !aRect.IsEmpty() )
|
|
{
|
|
Region aRegion( aRect );
|
|
ImplInvalidate( &aRegion, nFlags );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Invalidate( const Region& rRegion, sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
|
|
return;
|
|
|
|
if ( rRegion.IsNull() )
|
|
ImplInvalidate( NULL, nFlags );
|
|
else
|
|
{
|
|
Region aRegion = ImplPixelToDevicePixel( LogicToPixel( rRegion ) );
|
|
if ( !aRegion.IsEmpty() )
|
|
ImplInvalidate( &aRegion, nFlags );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Validate( sal_uInt16 nFlags )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( !IsDeviceOutputNecessary() || !mnOutWidth || !mnOutHeight )
|
|
return;
|
|
|
|
ImplValidate( NULL, nFlags );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::HasPaintEvent() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( !mpWindowImpl->mbReallyVisible )
|
|
return sal_False;
|
|
|
|
if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame )
|
|
return sal_True;
|
|
|
|
if ( mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINT )
|
|
return sal_True;
|
|
|
|
if ( !ImplIsOverlapWindow() )
|
|
{
|
|
const Window* pTempWindow = this;
|
|
do
|
|
{
|
|
pTempWindow = pTempWindow->ImplGetParent();
|
|
if ( pTempWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINTCHILDREN | IMPL_PAINT_PAINTALLCHILDREN) )
|
|
return sal_True;
|
|
}
|
|
while ( !pTempWindow->ImplIsOverlapWindow() );
|
|
}
|
|
|
|
return sal_False;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Update()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
{
|
|
mpWindowImpl->mpBorderWindow->Update();
|
|
return;
|
|
}
|
|
|
|
if ( !mpWindowImpl->mbReallyVisible )
|
|
return;
|
|
|
|
sal_Bool bFlush = sal_False;
|
|
if ( mpWindowImpl->mpFrameWindow->mpWindowImpl->mbPaintFrame )
|
|
{
|
|
Point aPoint( 0, 0 );
|
|
Region aRegion( Rectangle( aPoint, Size( mnOutWidth, mnOutHeight ) ) );
|
|
ImplInvalidateOverlapFrameRegion( aRegion );
|
|
if ( mpWindowImpl->mbFrame || (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) )
|
|
bFlush = sal_True;
|
|
}
|
|
|
|
// First we should skip all windows which are Paint-Transparent
|
|
Window* pUpdateWindow = this;
|
|
Window* pWindow = pUpdateWindow;
|
|
while ( !pWindow->ImplIsOverlapWindow() )
|
|
{
|
|
if ( !pWindow->mpWindowImpl->mbPaintTransparent )
|
|
{
|
|
pUpdateWindow = pWindow;
|
|
break;
|
|
}
|
|
pWindow = pWindow->ImplGetParent();
|
|
}
|
|
// In order to limit drawing, an update only draws the window which
|
|
// has PAINTALLCHILDREN set
|
|
pWindow = pUpdateWindow;
|
|
do
|
|
{
|
|
if ( pWindow->mpWindowImpl->mnPaintFlags & IMPL_PAINT_PAINTALLCHILDREN )
|
|
pUpdateWindow = pWindow;
|
|
if ( pWindow->ImplIsOverlapWindow() )
|
|
break;
|
|
pWindow = pWindow->ImplGetParent();
|
|
}
|
|
while ( pWindow );
|
|
|
|
// if there is something to paint, trigger a Paint
|
|
if ( pUpdateWindow->mpWindowImpl->mnPaintFlags & (IMPL_PAINT_PAINT | IMPL_PAINT_PAINTCHILDREN) )
|
|
{
|
|
// trigger an update also for system windows on top of us,
|
|
// otherwise holes would remain
|
|
Window* pUpdateOverlapWindow = ImplGetFirstOverlapWindow()->mpWindowImpl->mpFirstOverlap;
|
|
while ( pUpdateOverlapWindow )
|
|
{
|
|
pUpdateOverlapWindow->Update();
|
|
pUpdateOverlapWindow = pUpdateOverlapWindow->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
pUpdateWindow->ImplCallPaint( NULL, pUpdateWindow->mpWindowImpl->mnPaintFlags );
|
|
}
|
|
|
|
if ( bFlush )
|
|
Flush();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Flush()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
const Rectangle aWinRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
|
|
mpWindowImpl->mpFrame->Flush( aWinRect );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::Sync()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
mpWindowImpl->mpFrame->Sync();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetUpdateMode( sal_Bool bUpdate )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
mpWindowImpl->mbNoUpdate = !bUpdate;
|
|
StateChanged( STATE_CHANGE_UPDATEMODE );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::GrabFocus()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplGrabFocus( 0 );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::HasFocus() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
// #107575# the first floating window always has the keyboard focus, see also winproc.cxx: ImplGetKeyInputWindow()
|
|
// task was shifted to 6.y, so its commented out
|
|
/*
|
|
Window* pFocusWin = ImplGetSVData()->maWinData.mpFirstFloat;
|
|
if( pFocusWin && pFocusWin->mpWindowImpl->mbFloatWin && ((FloatingWindow *)pFocusWin)->GrabsFocus() )
|
|
pFocusWin = pFocusWin->GetPreferredKeyInputWindow();
|
|
else
|
|
pFocusWin = ImplGetSVData()->maWinData.mpFocusWin;
|
|
|
|
return (this == pFocusWin);
|
|
*/
|
|
|
|
return (this == ImplGetSVData()->maWinData.mpFocusWin);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::GrabFocusToDocument()
|
|
{
|
|
Window *pWin = this;
|
|
while( pWin )
|
|
{
|
|
if( !pWin->GetParent() )
|
|
{
|
|
pWin->ImplGetFrameWindow()->GetWindow( WINDOW_CLIENT )->GrabFocus();
|
|
return;
|
|
}
|
|
pWin = pWin->GetParent();
|
|
}
|
|
}
|
|
|
|
void Window::SetFakeFocus( bool bFocus )
|
|
{
|
|
ImplGetWindowImpl()->mbFakeFocusSet = bFocus;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::HasChildPathFocus( sal_Bool bSystemWindow ) const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
// #107575#, the first floating window always has the keyboard focus, see also winproc.cxx: ImplGetKeyInputWindow()
|
|
// task was shifted to 6.y, so its commented out
|
|
/*
|
|
Window* pFocusWin = ImplGetSVData()->maWinData.mpFirstFloat;
|
|
if( pFocusWin && pFocusWin->mpWindowImpl->mbFloatWin && ((FloatingWindow *)pFocusWin)->GrabsFocus() )
|
|
pFocusWin = pFocusWin->GetPreferredKeyInputWindow();
|
|
else
|
|
pFocusWin = ImplGetSVData()->maWinData.mpFocusWin;
|
|
*/
|
|
Window* pFocusWin = ImplGetSVData()->maWinData.mpFocusWin;
|
|
if ( pFocusWin )
|
|
return ImplIsWindowOrChild( pFocusWin, bSystemWindow );
|
|
return sal_False;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::CaptureMouse()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
|
|
// possibly stop tracking
|
|
if ( pSVData->maWinData.mpTrackWin != this )
|
|
{
|
|
if ( pSVData->maWinData.mpTrackWin )
|
|
pSVData->maWinData.mpTrackWin->EndTracking( ENDTRACK_CANCEL );
|
|
}
|
|
|
|
if ( pSVData->maWinData.mpCaptureWin != this )
|
|
{
|
|
pSVData->maWinData.mpCaptureWin = this;
|
|
mpWindowImpl->mpFrame->CaptureMouse( sal_True );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ReleaseMouse()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
ImplSVData* pSVData = ImplGetSVData();
|
|
|
|
DBG_ASSERTWARNING( pSVData->maWinData.mpCaptureWin == this,
|
|
"Window::ReleaseMouse(): window doesn't have the mouse capture" );
|
|
|
|
if ( pSVData->maWinData.mpCaptureWin == this )
|
|
{
|
|
pSVData->maWinData.mpCaptureWin = NULL;
|
|
mpWindowImpl->mpFrame->CaptureMouse( sal_False );
|
|
ImplGenerateMouseMove();
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::IsMouseCaptured() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
return (this == ImplGetSVData()->maWinData.mpCaptureWin);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetPointer( const Pointer& rPointer )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->maPointer == rPointer )
|
|
return;
|
|
|
|
mpWindowImpl->maPointer = rPointer;
|
|
|
|
// possibly immediately move pointer
|
|
if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
|
|
mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::EnableChildPointerOverwrite( sal_Bool bOverwrite )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mbChildPtrOverwrite == bOverwrite )
|
|
return;
|
|
|
|
mpWindowImpl->mbChildPtrOverwrite = bOverwrite;
|
|
|
|
// possibly immediately move pointer
|
|
if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
|
|
mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetPointerPosPixel( const Point& rPos )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
Point aPos = ImplOutputToFrame( rPos );
|
|
if( ImplHasMirroredGraphics() )
|
|
{
|
|
if( !IsRTLEnabled() )
|
|
{
|
|
// --- RTL --- (re-mirror mouse pos at this window)
|
|
ImplReMirror( aPos );
|
|
}
|
|
// mirroring is required here, SetPointerPos bypasses SalGraphics
|
|
mpGraphics->mirror( aPos.X(), this );
|
|
}
|
|
else if( ImplIsAntiparallel() )
|
|
{
|
|
ImplReMirror( aPos );
|
|
}
|
|
mpWindowImpl->mpFrame->SetPointerPos( aPos.X(), aPos.Y() );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Point Window::GetPointerPosPixel()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
Point aPos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY );
|
|
if( ImplIsAntiparallel() )
|
|
{
|
|
// --- RTL --- (re-mirror mouse pos at this window)
|
|
ImplReMirror( aPos );
|
|
}
|
|
return ImplFrameToOutput( aPos );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Point Window::GetLastPointerPosPixel()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
Point aPos( mpWindowImpl->mpFrameData->mnBeforeLastMouseX, mpWindowImpl->mpFrameData->mnBeforeLastMouseY );
|
|
if( ImplIsAntiparallel() )
|
|
{
|
|
// --- RTL --- (re-mirror mouse pos at this window)
|
|
ImplReMirror( aPos );
|
|
}
|
|
return ImplFrameToOutput( aPos );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ShowPointer( sal_Bool bVisible )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mbNoPtrVisible != !bVisible )
|
|
{
|
|
mpWindowImpl->mbNoPtrVisible = !bVisible;
|
|
|
|
// possibly immediately move pointer
|
|
if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
|
|
mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Window::PointerState Window::GetPointerState()
|
|
{
|
|
PointerState aState;
|
|
aState.mnState = 0;
|
|
|
|
if (mpWindowImpl->mpFrame)
|
|
{
|
|
SalFrame::SalPointerState aSalPointerState;
|
|
|
|
aSalPointerState = mpWindowImpl->mpFrame->GetPointerState();
|
|
if( ImplIsAntiparallel() )
|
|
{
|
|
// --- RTL --- (re-mirror mouse pos at this window)
|
|
ImplReMirror( aSalPointerState.maPos );
|
|
}
|
|
aState.maPos = ImplFrameToOutput( aSalPointerState.maPos );
|
|
aState.mnState = aSalPointerState.mnState;
|
|
}
|
|
return aState;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::IsMouseOver()
|
|
{
|
|
return ImplGetWinData()->mbMouseOver;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::EnterWait()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
mpWindowImpl->mnWaitCount++;
|
|
|
|
if ( mpWindowImpl->mnWaitCount == 1 )
|
|
{
|
|
// possibly immediately move pointer
|
|
if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
|
|
mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::LeaveWait()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mnWaitCount )
|
|
{
|
|
mpWindowImpl->mnWaitCount--;
|
|
|
|
if ( !mpWindowImpl->mnWaitCount )
|
|
{
|
|
// possibly immediately move pointer
|
|
if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
|
|
mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
|
|
}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetCursor( Cursor* pCursor )
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if ( mpWindowImpl->mpCursor != pCursor )
|
|
{
|
|
if ( mpWindowImpl->mpCursor )
|
|
mpWindowImpl->mpCursor->ImplHide( true );
|
|
mpWindowImpl->mpCursor = pCursor;
|
|
if ( pCursor )
|
|
pCursor->ImplShow();
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetText( const OUString& rStr )
|
|
{
|
|
if (rStr == OUString(mpWindowImpl->maText))
|
|
return;
|
|
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
String oldTitle( mpWindowImpl->maText );
|
|
mpWindowImpl->maText = rStr;
|
|
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->SetText( rStr );
|
|
else if ( mpWindowImpl->mbFrame )
|
|
mpWindowImpl->mpFrame->SetTitle( rStr );
|
|
|
|
ImplCallEventListeners( 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() )
|
|
{
|
|
Window* pWindow = GetAccessibleRelationLabelFor();
|
|
if ( pWindow && pWindow != this )
|
|
pWindow->ImplCallEventListeners( VCLEVENT_WINDOW_FRAMETITLECHANGED, &oldTitle );
|
|
}
|
|
|
|
StateChanged( STATE_CHANGE_TEXT );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
OUString Window::GetText() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
return mpWindowImpl->maText;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
OUString Window::GetDisplayText() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
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 XubString& Window::GetHelpText() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
String aStrHelpId( rtl::OStringToOUString( GetHelpId(), RTL_TEXTENCODING_UTF8 ) );
|
|
bool bStrHelpId = (aStrHelpId.Len() > 0);
|
|
|
|
if ( !mpWindowImpl->maHelpText.Len() && bStrHelpId )
|
|
{
|
|
if ( !IsDialog() && (mpWindowImpl->mnType != WINDOW_TABPAGE) && (mpWindowImpl->mnType != WINDOW_FLOATINGWINDOW) )
|
|
{
|
|
Help* pHelp = Application::GetHelp();
|
|
if ( pHelp )
|
|
{
|
|
((Window*)this)->mpWindowImpl->maHelpText = pHelp->GetHelpText( aStrHelpId, this );
|
|
mpWindowImpl->mbHelpTextDynamic = sal_False;
|
|
}
|
|
}
|
|
}
|
|
else if( mpWindowImpl->mbHelpTextDynamic && bStrHelpId )
|
|
{
|
|
static const char* pEnv = getenv( "HELP_DEBUG" );
|
|
if( pEnv && *pEnv )
|
|
{
|
|
rtl::OUStringBuffer aTxt( 64+mpWindowImpl->maHelpText.Len() );
|
|
aTxt.append( mpWindowImpl->maHelpText );
|
|
aTxt.appendAscii( "\n------------------\n" );
|
|
aTxt.append( rtl::OUString( aStrHelpId ) );
|
|
mpWindowImpl->maHelpText = aTxt.makeStringAndClear();
|
|
}
|
|
mpWindowImpl->mbHelpTextDynamic = sal_False;
|
|
}
|
|
|
|
return mpWindowImpl->maHelpText;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Window* Window::FindWindow( const Point& rPos ) const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
Point aPos = OutputToScreenPixel( rPos );
|
|
return ((Window*)this)->ImplFindWindow( aPos );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_uInt16 Window::GetChildCount() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
sal_uInt16 nChildCount = 0;
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
nChildCount++;
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
return nChildCount;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Window* Window::GetChild( sal_uInt16 nChild ) const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
sal_uInt16 nChildCount = 0;
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while ( pChild )
|
|
{
|
|
if ( nChild == nChildCount )
|
|
return pChild;
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
nChildCount++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
Window* Window::GetWindow( sal_uInt16 nType ) const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
switch ( nType )
|
|
{
|
|
case WINDOW_PARENT:
|
|
return mpWindowImpl->mpRealParent;
|
|
|
|
case WINDOW_FIRSTCHILD:
|
|
return mpWindowImpl->mpFirstChild;
|
|
|
|
case WINDOW_LASTCHILD:
|
|
return mpWindowImpl->mpLastChild;
|
|
|
|
case WINDOW_PREV:
|
|
return mpWindowImpl->mpPrev;
|
|
|
|
case WINDOW_NEXT:
|
|
return mpWindowImpl->mpNext;
|
|
|
|
case WINDOW_FIRSTOVERLAP:
|
|
return mpWindowImpl->mpFirstOverlap;
|
|
|
|
case WINDOW_LASTOVERLAP:
|
|
return mpWindowImpl->mpLastOverlap;
|
|
|
|
case WINDOW_OVERLAP:
|
|
if ( ImplIsOverlapWindow() )
|
|
return (Window*)this;
|
|
else
|
|
return mpWindowImpl->mpOverlapWindow;
|
|
|
|
case WINDOW_PARENTOVERLAP:
|
|
if ( ImplIsOverlapWindow() )
|
|
return mpWindowImpl->mpOverlapWindow;
|
|
else
|
|
return mpWindowImpl->mpOverlapWindow->mpWindowImpl->mpOverlapWindow;
|
|
|
|
case WINDOW_CLIENT:
|
|
return ((Window*)this)->ImplGetWindow();
|
|
|
|
case WINDOW_REALPARENT:
|
|
return ImplGetParent();
|
|
|
|
case WINDOW_FRAME:
|
|
return mpWindowImpl->mpFrameWindow;
|
|
|
|
case WINDOW_BORDER:
|
|
if ( mpWindowImpl->mpBorderWindow )
|
|
return mpWindowImpl->mpBorderWindow->GetWindow( WINDOW_BORDER );
|
|
return (Window*)this;
|
|
|
|
case WINDOW_FIRSTTOPWINDOWCHILD:
|
|
return ImplGetWinData()->maTopWindowChildren.empty() ? NULL : *ImplGetWinData()->maTopWindowChildren.begin();
|
|
|
|
case WINDOW_LASTTOPWINDOWCHILD:
|
|
return ImplGetWinData()->maTopWindowChildren.empty() ? NULL : *ImplGetWinData()->maTopWindowChildren.rbegin();
|
|
|
|
case WINDOW_PREVTOPWINDOWSIBLING:
|
|
{
|
|
if ( !mpWindowImpl->mpRealParent )
|
|
return NULL;
|
|
const ::std::list< Window* >& rTopWindows( mpWindowImpl->mpRealParent->ImplGetWinData()->maTopWindowChildren );
|
|
::std::list< Window* >::const_iterator myPos =
|
|
::std::find( rTopWindows.begin(), rTopWindows.end(), this );
|
|
if ( myPos == rTopWindows.end() )
|
|
return NULL;
|
|
if ( myPos == rTopWindows.begin() )
|
|
return NULL;
|
|
return *--myPos;
|
|
}
|
|
|
|
case WINDOW_NEXTTOPWINDOWSIBLING:
|
|
{
|
|
if ( !mpWindowImpl->mpRealParent )
|
|
return NULL;
|
|
const ::std::list< Window* >& rTopWindows( mpWindowImpl->mpRealParent->ImplGetWinData()->maTopWindowChildren );
|
|
::std::list< Window* >::const_iterator myPos =
|
|
::std::find( rTopWindows.begin(), rTopWindows.end(), this );
|
|
if ( ( myPos == rTopWindows.end() ) || ( ++myPos == rTopWindows.end() ) )
|
|
return NULL;
|
|
return *myPos;
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::IsChild( const Window* pWindow, sal_Bool bSystemWindow ) const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
DBG_CHKOBJ( pWindow, Window, ImplDbgCheckWindow );
|
|
|
|
do
|
|
{
|
|
if ( !bSystemWindow && pWindow->ImplIsOverlapWindow() )
|
|
break;
|
|
|
|
pWindow = pWindow->ImplGetParent();
|
|
|
|
if ( pWindow == this )
|
|
return sal_True;
|
|
}
|
|
while ( pWindow );
|
|
|
|
return sal_False;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
sal_Bool Window::IsWindowOrChild( const Window* pWindow, sal_Bool bSystemWindow ) const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
DBG_CHKOBJ( pWindow, Window, ImplDbgCheckWindow );
|
|
|
|
if ( this == pWindow )
|
|
return sal_True;
|
|
return ImplIsChild( pWindow, bSystemWindow );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
const SystemEnvData* Window::GetSystemData() const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
return mpWindowImpl->mpFrame ? mpWindowImpl->mpFrame->GetSystemData() : NULL;
|
|
}
|
|
|
|
::com::sun::star::uno::Any Window::GetSystemDataAny() const
|
|
{
|
|
::com::sun::star::uno::Any aRet;
|
|
const SystemEnvData* pSysData = GetSystemData();
|
|
if( pSysData )
|
|
{
|
|
::com::sun::star::uno::Sequence< sal_Int8 > aSeq( (sal_Int8*)pSysData, pSysData->nSize );
|
|
aRet <<= aSeq;
|
|
}
|
|
return aRet;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetWindowPeer( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xPeer, VCLXWindow* pVCLXWindow )
|
|
{
|
|
// be safe against re-entrance: first clear the old ref, then assign the new one
|
|
// #133706# / 2006-03-30 / frank.schoenheit@sun.com
|
|
mpWindowImpl->mxWindowPeer.clear();
|
|
mpWindowImpl->mxWindowPeer = xPeer;
|
|
|
|
mpWindowImpl->mpVCLXWindow = pVCLXWindow;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > Window::GetComponentInterface( sal_Bool bCreate )
|
|
{
|
|
if ( !mpWindowImpl->mxWindowPeer.is() && bCreate )
|
|
{
|
|
UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
|
|
if ( pWrapper )
|
|
mpWindowImpl->mxWindowPeer = pWrapper->GetWindowInterface( this, sal_True );
|
|
}
|
|
return mpWindowImpl->mxWindowPeer;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::SetComponentInterface( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > xIFace )
|
|
{
|
|
UnoWrapperBase* pWrapper = Application::GetUnoWrapper();
|
|
DBG_ASSERT( pWrapper, "SetComponentInterface: No Wrapper!" );
|
|
if ( pWrapper )
|
|
pWrapper->SetWindowInterface( this, xIFace );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplCallDeactivateListeners( Window *pNew )
|
|
{
|
|
// no deactivation if the newly activated window is my child
|
|
if ( !pNew || !ImplIsChild( pNew ) )
|
|
{
|
|
ImplDelData aDogtag( this );
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_DEACTIVATE );
|
|
if( aDogtag.IsDead() )
|
|
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( Window *pOld )
|
|
{
|
|
// no activation if the old active window is my child
|
|
if ( !pOld || !ImplIsChild( pOld ) )
|
|
{
|
|
ImplDelData aDogtag( this );
|
|
ImplCallEventListeners( VCLEVENT_WINDOW_ACTIVATE, pOld );
|
|
if( aDogtag.IsDead() )
|
|
return;
|
|
|
|
// #106298# revoke the change for 105369, because this change
|
|
// disabled the activate event for the parent,
|
|
// if the parent is a compound control
|
|
//if( !GetParent() || !GetParent()->IsCompoundControl() )
|
|
//{
|
|
// #100759#, avoid walking the wrong frame's hierarchy
|
|
// eg, undocked docking windows (ImplDockFloatWin)
|
|
// #104714#, revert the changes for 100759 because it has a side effect when pOld is a dialog
|
|
// additionally the gallery is not dockable anymore, so 100759 canot occur
|
|
if ( ImplGetParent() ) /* && mpWindowImpl->mpFrameWindow == ImplGetParent()->mpWindowImpl->mpFrameWindow ) */
|
|
ImplGetParent()->ImplCallActivateListeners( pOld );
|
|
else if( (mpWindowImpl->mnStyle & WB_INTROWIN) == 0 )
|
|
{
|
|
// top level frame reached: store hint for DefModalDialogParent
|
|
ImplGetSVData()->maWinData.mpActiveApplicationFrame = mpWindowImpl->mpFrameWindow;
|
|
}
|
|
//}
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
bool Window::ImplStopDnd()
|
|
{
|
|
bool bRet = false;
|
|
if( mpWindowImpl->mpFrameData && mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
|
|
{
|
|
bRet = true;
|
|
mpWindowImpl->mpFrameData->mxDropTarget.clear();
|
|
mpWindowImpl->mpFrameData->mxDragSource.clear();
|
|
mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::ImplStartDnd()
|
|
{
|
|
GetDropTarget();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
uno::Reference< XDropTarget > Window::GetDropTarget()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if( ! mpWindowImpl->mxDNDListenerContainer.is() )
|
|
{
|
|
sal_Int8 nDefaultActions = 0;
|
|
|
|
if( mpWindowImpl->mpFrameData )
|
|
{
|
|
if( ! mpWindowImpl->mpFrameData->mxDropTarget.is() )
|
|
{
|
|
// initialization is done in GetDragSource
|
|
uno::Reference< XDragSource > xDragSource = GetDragSource();
|
|
}
|
|
|
|
if( mpWindowImpl->mpFrameData->mxDropTarget.is() )
|
|
{
|
|
nDefaultActions = mpWindowImpl->mpFrameData->mxDropTarget->getDefaultActions();
|
|
|
|
if( ! mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
|
|
{
|
|
mpWindowImpl->mpFrameData->mxDropTargetListener = new DNDEventDispatcher( mpWindowImpl->mpFrameWindow );
|
|
|
|
try
|
|
{
|
|
mpWindowImpl->mpFrameData->mxDropTarget->addDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
|
|
|
|
// register also as drag gesture listener if directly supported by drag source
|
|
uno::Reference< XDragGestureRecognizer > xDragGestureRecognizer =
|
|
uno::Reference< XDragGestureRecognizer > (mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
|
|
|
|
if( xDragGestureRecognizer.is() )
|
|
{
|
|
xDragGestureRecognizer->addDragGestureListener(
|
|
uno::Reference< XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY));
|
|
}
|
|
else
|
|
mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = sal_True;
|
|
|
|
}
|
|
catch (const RuntimeException&)
|
|
{
|
|
// release all instances
|
|
mpWindowImpl->mpFrameData->mxDropTarget.clear();
|
|
mpWindowImpl->mpFrameData->mxDragSource.clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
mpWindowImpl->mxDNDListenerContainer = static_cast < XDropTarget * > ( new DNDListenerContainer( nDefaultActions ) );
|
|
}
|
|
|
|
// this object is located in the same process, so there will be no runtime exception
|
|
return uno::Reference< XDropTarget > ( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
uno::Reference< XDragSource > Window::GetDragSource()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if( mpWindowImpl->mpFrameData )
|
|
{
|
|
if( ! mpWindowImpl->mpFrameData->mxDragSource.is() )
|
|
{
|
|
try
|
|
{
|
|
uno::Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
|
|
const SystemEnvData * pEnvData = GetSystemData();
|
|
|
|
if( pEnvData )
|
|
{
|
|
Sequence< Any > aDragSourceAL( 2 ), aDropTargetAL( 2 );
|
|
OUString aDragSourceSN, aDropTargetSN;
|
|
#if defined WNT
|
|
aDragSourceSN = OUString("com.sun.star.datatransfer.dnd.OleDragSource");
|
|
aDropTargetSN = OUString("com.sun.star.datatransfer.dnd.OleDropTarget");
|
|
aDragSourceAL[ 1 ] = makeAny( (sal_uInt32) pEnvData->hWnd );
|
|
aDropTargetAL[ 0 ] = makeAny( (sal_uInt32) pEnvData->hWnd );
|
|
#elif defined MACOSX
|
|
/* FIXME: Mac OS X specific dnd interface does not exist! *
|
|
* Using Windows based dnd as a temporary solution */
|
|
aDragSourceSN = OUString("com.sun.star.datatransfer.dnd.OleDragSource");
|
|
aDropTargetSN = OUString("com.sun.star.datatransfer.dnd.OleDropTarget");
|
|
aDragSourceAL[ 1 ] = makeAny( static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->pView) ) );
|
|
aDropTargetAL[ 0 ] = makeAny( static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->pView) ) );
|
|
#elif defined IOS
|
|
/* What does LibreOffice's use of DND concepts mean on
|
|
* iOS, huh, is this both inter-app DND (which clearly is
|
|
* meaningless), or intra-app? Anyway, use the same code
|
|
* as for MacOSX for now, even if meaningless...
|
|
*/
|
|
aDragSourceSN = OUString("com.sun.star.datatransfer.dnd.OleDragSource");
|
|
aDropTargetSN = OUString("com.sun.star.datatransfer.dnd.OleDropTarget");
|
|
aDragSourceAL[ 1 ] = makeAny( static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->pView) ) );
|
|
aDropTargetAL[ 0 ] = makeAny( static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->pView) ) );
|
|
#elif defined UNX
|
|
aDropTargetAL.realloc( 3 );
|
|
aDragSourceAL.realloc( 3 );
|
|
aDragSourceSN = OUString("com.sun.star.datatransfer.dnd.X11DragSource");
|
|
aDropTargetSN = OUString("com.sun.star.datatransfer.dnd.X11DropTarget");
|
|
|
|
aDragSourceAL[ 0 ] = makeAny( Application::GetDisplayConnection() );
|
|
aDragSourceAL[ 2 ] = makeAny( vcl::createBmpConverter() );
|
|
aDropTargetAL[ 0 ] = makeAny( Application::GetDisplayConnection() );
|
|
aDropTargetAL[ 1 ] = makeAny( (sal_Size)(pEnvData->aShellWindow) );
|
|
aDropTargetAL[ 2 ] = makeAny( vcl::createBmpConverter() );
|
|
#endif
|
|
if( !aDragSourceSN.isEmpty() )
|
|
mpWindowImpl->mpFrameData->mxDragSource = uno::Reference< XDragSource > ( xFactory->createInstanceWithArguments( aDragSourceSN, aDragSourceAL ), UNO_QUERY );
|
|
|
|
if( !aDropTargetSN.isEmpty() )
|
|
mpWindowImpl->mpFrameData->mxDropTarget = uno::Reference< XDropTarget > ( xFactory->createInstanceWithArguments( aDropTargetSN, aDropTargetAL ), UNO_QUERY );
|
|
}
|
|
}
|
|
|
|
// createInstance can throw any exception
|
|
catch (const Exception&)
|
|
{
|
|
// release all instances
|
|
mpWindowImpl->mpFrameData->mxDropTarget.clear();
|
|
mpWindowImpl->mpFrameData->mxDragSource.clear();
|
|
}
|
|
}
|
|
|
|
return mpWindowImpl->mpFrameData->mxDragSource;
|
|
}
|
|
|
|
return uno::Reference< XDragSource > ();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
uno::Reference< XDragGestureRecognizer > Window::GetDragGestureRecognizer()
|
|
{
|
|
return uno::Reference< XDragGestureRecognizer > ( GetDropTarget(), UNO_QUERY );
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
uno::Reference< XClipboard > Window::GetClipboard()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if( mpWindowImpl->mpFrameData )
|
|
{
|
|
if( ! mpWindowImpl->mpFrameData->mxClipboard.is() )
|
|
{
|
|
try
|
|
{
|
|
uno::Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
|
|
uno::Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
|
|
|
|
mpWindowImpl->mpFrameData->mxClipboard = uno::Reference< XClipboard >( xFactory->createInstance( OUString("com.sun.star.datatransfer.clipboard.SystemClipboardExt") ), UNO_QUERY );
|
|
|
|
if( !mpWindowImpl->mpFrameData->mxClipboard.is() )
|
|
{
|
|
Reference<XSystemClipboard> xSystemClipboard;
|
|
#if defined(UNX) && !defined(MACOSX) // unix clipboard needs to be initialized
|
|
xSystemClipboard = SystemClipboard::createUnix( xContext, Application::GetDisplayConnection(), "CLIPBOARD", vcl::createBmpConverter() );
|
|
#else
|
|
xSystemClipboard = SystemClipboard::createDefault(xContext);
|
|
#endif
|
|
mpWindowImpl->mpFrameData->mxClipboard = uno::Reference< XClipboard >( xSystemClipboard, UNO_QUERY );
|
|
}
|
|
}
|
|
// createInstance can throw any exception
|
|
catch (const Exception&)
|
|
{
|
|
// release all instances
|
|
mpWindowImpl->mpFrameData->mxClipboard.clear();
|
|
}
|
|
}
|
|
|
|
return mpWindowImpl->mpFrameData->mxClipboard;
|
|
}
|
|
|
|
return static_cast < XClipboard * > (0);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
uno::Reference< XClipboard > Window::GetPrimarySelection()
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if( mpWindowImpl->mpFrameData )
|
|
{
|
|
if( ! mpWindowImpl->mpFrameData->mxSelection.is() )
|
|
{
|
|
try
|
|
{
|
|
uno::Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
|
|
uno::Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
|
|
|
|
#if defined(UNX) && !defined(MACOSX)
|
|
Reference<XSystemClipboard> xSystemClipboard = SystemClipboard::createUnix( xContext, Application::GetDisplayConnection(), "PRIMARY", vcl::createBmpConverter() );
|
|
mpWindowImpl->mpFrameData->mxSelection = uno::Reference< XClipboard >( xSystemClipboard, UNO_QUERY );
|
|
# else
|
|
static uno::Reference< XClipboard > s_xSelection;
|
|
|
|
if ( !s_xSelection.is() )
|
|
s_xSelection = uno::Reference< XClipboard >( xFactory->createInstance( OUString("com.sun.star.datatransfer.clipboard.GenericClipboardExt") ), UNO_QUERY );
|
|
|
|
if ( !s_xSelection.is() )
|
|
s_xSelection = uno::Reference< XClipboard >( xFactory->createInstance( OUString("com.sun.star.datatransfer.clipboard.GenericClipboard") ), UNO_QUERY );
|
|
|
|
mpWindowImpl->mpFrameData->mxSelection = s_xSelection;
|
|
# endif
|
|
}
|
|
|
|
// createInstance can throw any exception
|
|
catch (const Exception&)
|
|
{
|
|
// release all instances
|
|
mpWindowImpl->mpFrameData->mxSelection.clear();
|
|
}
|
|
}
|
|
|
|
return mpWindowImpl->mpFrameData->mxSelection;
|
|
}
|
|
|
|
return static_cast < XClipboard * > (0);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
// Accessibility
|
|
// -----------------------------------------------------------------------
|
|
|
|
::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > Window::GetAccessible( sal_Bool bCreate )
|
|
{
|
|
// do not optimize hierarchy for the top level border win (ie, when there is no parent)
|
|
/* // do not optimize accessible hierarchy at all to better reflect real VCL hierarchy
|
|
if ( GetParent() && ( GetType() == WINDOW_BORDERWINDOW ) && ( GetChildCount() == 1 ) )
|
|
//if( !ImplIsAccessibleCandidate() )
|
|
{
|
|
Window* pChild = GetAccessibleChildWindow( 0 );
|
|
if ( pChild )
|
|
return pChild->GetAccessible();
|
|
}
|
|
*/
|
|
if ( !mpWindowImpl->mxAccessible.is() && bCreate )
|
|
mpWindowImpl->mxAccessible = CreateAccessible();
|
|
|
|
return mpWindowImpl->mxAccessible;
|
|
}
|
|
|
|
::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > Window::CreateAccessible()
|
|
{
|
|
::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc( GetComponentInterface( sal_True ), ::com::sun::star::uno::UNO_QUERY );
|
|
return xAcc;
|
|
}
|
|
|
|
void Window::SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > x )
|
|
{
|
|
mpWindowImpl->mxAccessible = x;
|
|
}
|
|
|
|
// skip all border windows that are no top level frames
|
|
sal_Bool Window::ImplIsAccessibleCandidate() const
|
|
{
|
|
if( !mpWindowImpl->mbBorderWin )
|
|
return sal_True;
|
|
else
|
|
// #101741 do not check for WB_CLOSEABLE because undecorated floaters (like menus!) are closeable
|
|
if( mpWindowImpl->mbFrame && mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) )
|
|
return sal_True;
|
|
else
|
|
return sal_False;
|
|
}
|
|
|
|
sal_Bool Window::ImplIsAccessibleNativeFrame() const
|
|
{
|
|
if( mpWindowImpl->mbFrame )
|
|
// #101741 do not check for WB_CLOSEABLE because undecorated floaters (like menus!) are closeable
|
|
if( (mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE)) )
|
|
return sal_True;
|
|
else
|
|
return sal_False;
|
|
else
|
|
return sal_False;
|
|
}
|
|
|
|
sal_uInt16 Window::ImplGetAccessibleCandidateChildWindowCount( sal_uInt16 nFirstWindowType ) const
|
|
{
|
|
sal_uInt16 nChildren = 0;
|
|
Window* pChild = GetWindow( nFirstWindowType );
|
|
while ( pChild )
|
|
{
|
|
if( pChild->ImplIsAccessibleCandidate() )
|
|
nChildren++;
|
|
else
|
|
nChildren = sal::static_int_cast<sal_uInt16>(nChildren + pChild->ImplGetAccessibleCandidateChildWindowCount( WINDOW_FIRSTCHILD ));
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
return nChildren;
|
|
}
|
|
|
|
Window* Window::ImplGetAccessibleCandidateChild( sal_uInt16 nChild, sal_uInt16& rChildCount, sal_uInt16 nFirstWindowType, sal_Bool bTopLevel ) const
|
|
{
|
|
DBG_CHKTHIS( Window, ImplDbgCheckWindow );
|
|
|
|
if( bTopLevel )
|
|
rChildCount = 0;
|
|
|
|
Window* pChild = GetWindow( nFirstWindowType );
|
|
while ( pChild )
|
|
{
|
|
Window *pTmpChild = pChild;
|
|
|
|
if( !pChild->ImplIsAccessibleCandidate() )
|
|
pTmpChild = pChild->ImplGetAccessibleCandidateChild( nChild, rChildCount, WINDOW_FIRSTCHILD, sal_False );
|
|
|
|
if ( nChild == rChildCount )
|
|
return pTmpChild;
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
rChildCount++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
Window* Window::GetAccessibleParentWindow() const
|
|
{
|
|
if ( ImplIsAccessibleNativeFrame() )
|
|
return NULL;
|
|
|
|
Window* pParent = mpWindowImpl->mpParent;
|
|
if( GetType() == WINDOW_MENUBARWINDOW )
|
|
{
|
|
// report the menubar as a child of THE workwindow
|
|
Window *pWorkWin = GetParent()->mpWindowImpl->mpFirstChild;
|
|
while( pWorkWin && (pWorkWin == this) )
|
|
pWorkWin = pWorkWin->mpWindowImpl->mpNext;
|
|
pParent = pWorkWin;
|
|
}
|
|
// If this is a floating window which has a native border window, then that border should be reported as
|
|
// the accessible parent, unless the floating window is a PopupMenuFloatingWindow
|
|
//
|
|
// The logic here has to match that of AccessibleFactory::createAccessibleContext in
|
|
// accessibility/source/helper/acc_factory.cxx to avoid PopupMenuFloatingWindow
|
|
// becoming a11y parents of themselves
|
|
else if( GetType() == WINDOW_FLOATINGWINDOW &&
|
|
mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame &&
|
|
!PopupMenuFloatingWindow::isPopupMenu(this))
|
|
{
|
|
pParent = mpWindowImpl->mpBorderWindow;
|
|
}
|
|
else if( pParent && !pParent->ImplIsAccessibleCandidate() )
|
|
{
|
|
pParent = pParent->mpWindowImpl->mpParent;
|
|
}
|
|
return pParent;
|
|
}
|
|
|
|
sal_uInt16 Window::GetAccessibleChildWindowCount()
|
|
{
|
|
sal_uInt16 nChildren = 0;
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while( pChild )
|
|
{
|
|
if( pChild->IsVisible() )
|
|
nChildren++;
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
// #107176# ignore overlapwindows
|
|
// this only affects non-system floating windows
|
|
// which are either not accessible (like the HelpAgent) or should be changed to system windows anyway
|
|
/*
|
|
if( ImplIsOverlapWindow() )
|
|
{
|
|
Window* pOverlap = GetWindow( WINDOW_FIRSTOVERLAP );
|
|
while ( pOverlap )
|
|
{
|
|
if( pOverlap->IsVisible() )
|
|
nChildren++;
|
|
pOverlap = pOverlap->GetWindow( WINDOW_NEXT );
|
|
}
|
|
}
|
|
*/
|
|
|
|
// report the menubarwindow as a child of THE workwindow
|
|
if( GetType() == WINDOW_BORDERWINDOW )
|
|
{
|
|
if( ((ImplBorderWindow *) this)->mpMenuBarWindow &&
|
|
((ImplBorderWindow *) this)->mpMenuBarWindow->IsVisible()
|
|
)
|
|
--nChildren;
|
|
}
|
|
else if( GetType() == WINDOW_WORKWINDOW )
|
|
{
|
|
if( ((WorkWindow *) this)->GetMenuBar() &&
|
|
((WorkWindow *) this)->GetMenuBar()->GetWindow() &&
|
|
((WorkWindow *) this)->GetMenuBar()->GetWindow()->IsVisible()
|
|
)
|
|
++nChildren;
|
|
}
|
|
|
|
return nChildren;
|
|
}
|
|
|
|
Window* Window::GetAccessibleChildWindow( sal_uInt16 n )
|
|
{
|
|
// report the menubarwindow as a the first child of THE workwindow
|
|
if( GetType() == WINDOW_WORKWINDOW && ((WorkWindow *) this)->GetMenuBar() )
|
|
{
|
|
if( n == 0 )
|
|
{
|
|
MenuBar *pMenuBar = ((WorkWindow *) this)->GetMenuBar();
|
|
if( pMenuBar->GetWindow() && pMenuBar->GetWindow()->IsVisible() )
|
|
return pMenuBar->GetWindow();
|
|
}
|
|
else
|
|
--n;
|
|
}
|
|
|
|
// transform n to child number including invisible children
|
|
sal_uInt16 nChildren = n;
|
|
Window* pChild = mpWindowImpl->mpFirstChild;
|
|
while( pChild )
|
|
{
|
|
if( pChild->IsVisible() )
|
|
{
|
|
if( ! nChildren )
|
|
break;
|
|
nChildren--;
|
|
}
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
|
|
if( GetType() == WINDOW_BORDERWINDOW && pChild && pChild->GetType() == WINDOW_MENUBARWINDOW )
|
|
{
|
|
do pChild = pChild->mpWindowImpl->mpNext; while( pChild && ! pChild->IsVisible() );
|
|
DBG_ASSERT( pChild, "GetAccessibleChildWindow(): wrong index in border window");
|
|
}
|
|
if ( !pChild )
|
|
{
|
|
// #107176# ignore overlapwindows
|
|
/*
|
|
if( ImplIsOverlapWindow() )
|
|
{
|
|
Window* pOverlap = GetWindow( WINDOW_FIRSTOVERLAP );
|
|
while ( !pChild && pOverlap )
|
|
{
|
|
if ( !nChildren && pOverlap->IsVisible() )
|
|
{
|
|
pChild = pOverlap;
|
|
break;
|
|
}
|
|
pOverlap = pOverlap->GetWindow( WINDOW_NEXT );
|
|
if( pOverlap && pOverlap->IsVisible() )
|
|
nChildren--;
|
|
}
|
|
}
|
|
*/
|
|
|
|
}
|
|
if ( pChild && ( pChild->GetType() == WINDOW_BORDERWINDOW ) && ( pChild->GetChildCount() == 1 ) )
|
|
{
|
|
pChild = pChild->GetChild( 0 );
|
|
}
|
|
return pChild;
|
|
}
|
|
|
|
|
|
void Window::SetAccessibleRole( sal_uInt16 nRole )
|
|
{
|
|
if ( !mpWindowImpl->mpAccessibleInfos )
|
|
mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
|
|
|
|
DBG_ASSERT( mpWindowImpl->mpAccessibleInfos->nAccessibleRole == 0xFFFF, "AccessibleRole already set!" );
|
|
mpWindowImpl->mpAccessibleInfos->nAccessibleRole = nRole;
|
|
}
|
|
|
|
sal_uInt16 Window::getDefaultAccessibleRole() const
|
|
{
|
|
sal_uInt16 nRole = 0xFFFF;
|
|
switch ( GetType() )
|
|
{
|
|
case WINDOW_MESSBOX: // MT: Would be nice to have special roles!
|
|
case WINDOW_INFOBOX:
|
|
case WINDOW_WARNINGBOX:
|
|
case WINDOW_ERRORBOX:
|
|
case WINDOW_QUERYBOX: nRole = accessibility::AccessibleRole::ALERT; break;
|
|
|
|
case WINDOW_MODELESSDIALOG:
|
|
case WINDOW_MODALDIALOG:
|
|
case WINDOW_SYSTEMDIALOG:
|
|
case WINDOW_PRINTERSETUPDIALOG:
|
|
case WINDOW_PRINTDIALOG:
|
|
case WINDOW_TABDIALOG:
|
|
case WINDOW_BUTTONDIALOG:
|
|
case WINDOW_DIALOG: nRole = accessibility::AccessibleRole::DIALOG; break;
|
|
|
|
case WINDOW_PUSHBUTTON:
|
|
case WINDOW_OKBUTTON:
|
|
case WINDOW_CANCELBUTTON:
|
|
case WINDOW_HELPBUTTON:
|
|
case WINDOW_IMAGEBUTTON:
|
|
case WINDOW_MENUBUTTON:
|
|
case WINDOW_MOREBUTTON:
|
|
case WINDOW_SPINBUTTON:
|
|
case WINDOW_BUTTON: nRole = accessibility::AccessibleRole::PUSH_BUTTON; break;
|
|
|
|
case WINDOW_PATHDIALOG: nRole = accessibility::AccessibleRole::DIRECTORY_PANE; break;
|
|
case WINDOW_FILEDIALOG: nRole = accessibility::AccessibleRole::FILE_CHOOSER; break;
|
|
case WINDOW_COLORDIALOG: nRole = accessibility::AccessibleRole::COLOR_CHOOSER; break;
|
|
case WINDOW_FONTDIALOG: nRole = accessibility::AccessibleRole::FONT_CHOOSER; break;
|
|
|
|
case WINDOW_IMAGERADIOBUTTON:
|
|
case WINDOW_RADIOBUTTON: nRole = accessibility::AccessibleRole::RADIO_BUTTON; break;
|
|
case WINDOW_TRISTATEBOX:
|
|
case WINDOW_CHECKBOX: nRole = accessibility::AccessibleRole::CHECK_BOX; break;
|
|
|
|
case WINDOW_MULTILINEEDIT: nRole = accessibility::AccessibleRole::SCROLL_PANE; break;
|
|
|
|
case WINDOW_PATTERNFIELD:
|
|
case WINDOW_NUMERICFIELD:
|
|
case WINDOW_METRICFIELD:
|
|
case WINDOW_CURRENCYFIELD:
|
|
case WINDOW_LONGCURRENCYFIELD:
|
|
case WINDOW_CALCINPUTLINE:
|
|
case WINDOW_EDIT: nRole = ( GetStyle() & WB_PASSWORD ) ? (accessibility::AccessibleRole::PASSWORD_TEXT) : (accessibility::AccessibleRole::TEXT); break;
|
|
|
|
case WINDOW_PATTERNBOX:
|
|
case WINDOW_NUMERICBOX:
|
|
case WINDOW_METRICBOX:
|
|
case WINDOW_CURRENCYBOX:
|
|
case WINDOW_LONGCURRENCYBOX:
|
|
case WINDOW_COMBOBOX: nRole = accessibility::AccessibleRole::COMBO_BOX; break;
|
|
|
|
case WINDOW_LISTBOX:
|
|
case WINDOW_MULTILISTBOX: nRole = accessibility::AccessibleRole::LIST; break;
|
|
|
|
case WINDOW_TREELISTBOX: nRole = accessibility::AccessibleRole::TREE; break;
|
|
|
|
case WINDOW_FIXEDTEXT: nRole = accessibility::AccessibleRole::LABEL; break;
|
|
case WINDOW_FIXEDLINE: nRole = accessibility::AccessibleRole::SEPARATOR; break;
|
|
case WINDOW_FIXEDBITMAP:
|
|
case WINDOW_FIXEDIMAGE: nRole = accessibility::AccessibleRole::ICON; break;
|
|
case WINDOW_GROUPBOX: nRole = accessibility::AccessibleRole::GROUP_BOX; break;
|
|
case WINDOW_SCROLLBAR: nRole = accessibility::AccessibleRole::SCROLL_BAR; break;
|
|
|
|
case WINDOW_SLIDER:
|
|
case WINDOW_SPLITTER:
|
|
case WINDOW_SPLITWINDOW: nRole = accessibility::AccessibleRole::SPLIT_PANE; break;
|
|
|
|
case WINDOW_DATEBOX:
|
|
case WINDOW_TIMEBOX:
|
|
case WINDOW_DATEFIELD:
|
|
case WINDOW_TIMEFIELD: nRole = accessibility::AccessibleRole::DATE_EDITOR; break;
|
|
|
|
case WINDOW_SPINFIELD: nRole = accessibility::AccessibleRole::SPIN_BOX; break;
|
|
|
|
case WINDOW_TOOLBOX: nRole = accessibility::AccessibleRole::TOOL_BAR; break;
|
|
case WINDOW_STATUSBAR: nRole = accessibility::AccessibleRole::STATUS_BAR; break;
|
|
|
|
case WINDOW_TABPAGE: nRole = accessibility::AccessibleRole::PANEL; break;
|
|
case WINDOW_TABCONTROL: nRole = accessibility::AccessibleRole::PAGE_TAB_LIST; break;
|
|
|
|
case WINDOW_DOCKINGWINDOW:
|
|
case WINDOW_SYSWINDOW: nRole = (mpWindowImpl->mbFrame) ? accessibility::AccessibleRole::FRAME :
|
|
accessibility::AccessibleRole::PANEL; break;
|
|
|
|
case WINDOW_FLOATINGWINDOW: nRole = ( mpWindowImpl->mbFrame ||
|
|
(mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) ||
|
|
(GetStyle() & WB_OWNERDRAWDECORATION) ) ? accessibility::AccessibleRole::FRAME :
|
|
accessibility::AccessibleRole::WINDOW; break;
|
|
|
|
case WINDOW_WORKWINDOW: nRole = accessibility::AccessibleRole::ROOT_PANE; break;
|
|
|
|
|
|
case WINDOW_SCROLLBARBOX: nRole = accessibility::AccessibleRole::FILLER; break;
|
|
|
|
case WINDOW_HELPTEXTWINDOW: nRole = accessibility::AccessibleRole::TOOL_TIP; break;
|
|
|
|
case WINDOW_RULER: nRole = accessibility::AccessibleRole::RULER; break;
|
|
|
|
case WINDOW_SCROLLWINDOW: nRole = accessibility::AccessibleRole::SCROLL_PANE; break;
|
|
|
|
case WINDOW_WINDOW:
|
|
case WINDOW_CONTROL:
|
|
case WINDOW_BORDERWINDOW:
|
|
case WINDOW_SYSTEMCHILDWINDOW:
|
|
default:
|
|
if (ImplIsAccessibleNativeFrame() )
|
|
nRole = accessibility::AccessibleRole::FRAME;
|
|
else if( IsScrollable() )
|
|
nRole = accessibility::AccessibleRole::SCROLL_PANE;
|
|
else if( ((Window*)this)->ImplGetWindow()->IsMenuFloatingWindow() )
|
|
nRole = accessibility::AccessibleRole::WINDOW; // #106002#, contextmenus are windows (i.e. toplevel)
|
|
else
|
|
// #104051# WINDOW seems to be a bad default role, use LAYEREDPANE instead
|
|
// a WINDOW is interpreted as a top-level window, which is typically not the case
|
|
//nRole = accessibility::AccessibleRole::WINDOW;
|
|
nRole = accessibility::AccessibleRole::PANEL;
|
|
}
|
|
return nRole;
|
|
}
|
|
|
|
sal_uInt16 Window::GetAccessibleRole() const
|
|
{
|
|
using namespace ::com::sun::star;
|
|
|
|
sal_uInt16 nRole = mpWindowImpl->mpAccessibleInfos ? mpWindowImpl->mpAccessibleInfos->nAccessibleRole : 0xFFFF;
|
|
if ( nRole == 0xFFFF )
|
|
nRole = getDefaultAccessibleRole();
|
|
return nRole;
|
|
}
|
|
|
|
void Window::SetAccessibleName( const String& rName )
|
|
{
|
|
if ( !mpWindowImpl->mpAccessibleInfos )
|
|
mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
|
|
|
|
delete mpWindowImpl->mpAccessibleInfos->pAccessibleName;
|
|
mpWindowImpl->mpAccessibleInfos->pAccessibleName = new String( rName );
|
|
}
|
|
|
|
String Window::GetAccessibleName() const
|
|
{
|
|
if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleName)
|
|
return *mpWindowImpl->mpAccessibleInfos->pAccessibleName;
|
|
return getDefaultAccessibleName();
|
|
}
|
|
|
|
OUString Window::getDefaultAccessibleName() const
|
|
{
|
|
OUString aAccessibleName;
|
|
switch ( GetType() )
|
|
{
|
|
case WINDOW_MULTILINEEDIT:
|
|
case WINDOW_PATTERNFIELD:
|
|
case WINDOW_NUMERICFIELD:
|
|
case WINDOW_METRICFIELD:
|
|
case WINDOW_CURRENCYFIELD:
|
|
case WINDOW_LONGCURRENCYFIELD:
|
|
case WINDOW_CALCINPUTLINE:
|
|
case WINDOW_EDIT:
|
|
|
|
case WINDOW_DATEBOX:
|
|
case WINDOW_TIMEBOX:
|
|
case WINDOW_CURRENCYBOX:
|
|
case WINDOW_LONGCURRENCYBOX:
|
|
case WINDOW_DATEFIELD:
|
|
case WINDOW_TIMEFIELD:
|
|
case WINDOW_SPINFIELD:
|
|
|
|
case WINDOW_COMBOBOX:
|
|
case WINDOW_LISTBOX:
|
|
case WINDOW_MULTILISTBOX:
|
|
case WINDOW_TREELISTBOX:
|
|
case WINDOW_METRICBOX:
|
|
{
|
|
Window *pLabel = GetAccessibleRelationLabeledBy();
|
|
if ( pLabel && pLabel != this )
|
|
aAccessibleName = pLabel->GetText();
|
|
}
|
|
break;
|
|
|
|
case WINDOW_IMAGEBUTTON:
|
|
case WINDOW_PUSHBUTTON:
|
|
aAccessibleName = GetText();
|
|
if (aAccessibleName.isEmpty())
|
|
{
|
|
aAccessibleName = GetQuickHelpText();
|
|
if (aAccessibleName.isEmpty())
|
|
aAccessibleName = GetHelpText();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
aAccessibleName = GetText();
|
|
break;
|
|
}
|
|
|
|
return GetNonMnemonicString( aAccessibleName );
|
|
}
|
|
|
|
void Window::SetAccessibleDescription( const String& rDescription )
|
|
{
|
|
if ( ! mpWindowImpl->mpAccessibleInfos )
|
|
mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
|
|
|
|
DBG_ASSERT( !mpWindowImpl->mpAccessibleInfos->pAccessibleDescription, "AccessibleDescription already set!" );
|
|
delete mpWindowImpl->mpAccessibleInfos->pAccessibleDescription;
|
|
mpWindowImpl->mpAccessibleInfos->pAccessibleDescription = new String( rDescription );
|
|
}
|
|
|
|
String Window::GetAccessibleDescription() const
|
|
{
|
|
String aAccessibleDescription;
|
|
if ( mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleDescription )
|
|
{
|
|
aAccessibleDescription = *mpWindowImpl->mpAccessibleInfos->pAccessibleDescription;
|
|
}
|
|
else
|
|
{
|
|
// Special code for help text windows. ZT asks the border window for the
|
|
// description so we have to forward this request to our inner window.
|
|
const Window* pWin = ((Window *)this)->ImplGetWindow();
|
|
if ( pWin->GetType() == WINDOW_HELPTEXTWINDOW )
|
|
aAccessibleDescription = pWin->GetHelpText();
|
|
else
|
|
aAccessibleDescription = GetHelpText();
|
|
}
|
|
|
|
return aAccessibleDescription;
|
|
}
|
|
|
|
void Window::SetAccessibleRelationLabeledBy( Window* pLabeledBy )
|
|
{
|
|
if ( !mpWindowImpl->mpAccessibleInfos )
|
|
mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
|
|
mpWindowImpl->mpAccessibleInfos->pLabeledByWindow = pLabeledBy;
|
|
}
|
|
|
|
void Window::SetAccessibleRelationLabelFor( Window* pLabelFor )
|
|
{
|
|
if ( !mpWindowImpl->mpAccessibleInfos )
|
|
mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
|
|
mpWindowImpl->mpAccessibleInfos->pLabelForWindow = pLabelFor;
|
|
}
|
|
|
|
void Window::SetAccessibleRelationMemberOf( Window* pMemberOfWin )
|
|
{
|
|
if ( !mpWindowImpl->mpAccessibleInfos )
|
|
mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
|
|
mpWindowImpl->mpAccessibleInfos->pMemberOfWindow = pMemberOfWin;
|
|
}
|
|
|
|
Window* Window::GetAccessibleRelationMemberOf() const
|
|
{
|
|
if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pMemberOfWindow)
|
|
return mpWindowImpl->mpAccessibleInfos->pMemberOfWindow;
|
|
|
|
if (!isContainerWindow(this) && !isContainerWindow(GetParent()))
|
|
return getLegacyNonLayoutAccessibleRelationMemberOf();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
Window* Window::getAccessibleRelationLabelFor() const
|
|
{
|
|
if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pLabelForWindow)
|
|
return mpWindowImpl->mpAccessibleInfos->pLabelForWindow;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
Window* Window::GetAccessibleRelationLabelFor() const
|
|
{
|
|
Window* pWindow = getAccessibleRelationLabelFor();
|
|
|
|
if (pWindow)
|
|
return pWindow;
|
|
|
|
if (!isContainerWindow(this) && !isContainerWindow(GetParent()))
|
|
return getLegacyNonLayoutAccessibleRelationLabelFor();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
Window* Window::GetAccessibleRelationLabeledBy() const
|
|
{
|
|
if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pLabeledByWindow)
|
|
return mpWindowImpl->mpAccessibleInfos->pLabeledByWindow;
|
|
|
|
std::vector<FixedText*> m_aMnemonicLabels(list_mnemonic_labels());
|
|
if (!m_aMnemonicLabels.empty())
|
|
{
|
|
SAL_WARN_IF(m_aMnemonicLabels.size() != 1, "vcl.a11y", "TODO: multiple LabeledBy not handled yet");
|
|
return m_aMnemonicLabels[0];
|
|
}
|
|
|
|
if (!isContainerWindow(this) && !isContainerWindow(GetParent()))
|
|
return getLegacyNonLayoutAccessibleRelationLabeledBy();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
sal_Bool Window::IsAccessibilityEventsSuppressed( sal_Bool bTraverseParentPath )
|
|
{
|
|
if( !bTraverseParentPath )
|
|
return mpWindowImpl->mbSuppressAccessibilityEvents;
|
|
else
|
|
{
|
|
Window *pParent = this;
|
|
while ( pParent && pParent->mpWindowImpl)
|
|
{
|
|
if( pParent->mpWindowImpl->mbSuppressAccessibilityEvents )
|
|
return sal_True;
|
|
else
|
|
pParent = pParent->mpWindowImpl->mpParent; // do not use GetParent() to find borderwindows that are frames
|
|
}
|
|
return sal_False;
|
|
}
|
|
}
|
|
|
|
void Window::SetAccessibilityEventsSuppressed(sal_Bool bSuppressed)
|
|
{
|
|
mpWindowImpl->mbSuppressAccessibilityEvents = bSuppressed;
|
|
}
|
|
|
|
void Window::RecordLayoutData( vcl::ControlLayoutData* pLayout, const Rectangle& rRect )
|
|
{
|
|
if( ! mpOutDevData )
|
|
ImplInitOutDevData();
|
|
mpOutDevData->mpRecordLayout = pLayout;
|
|
mpOutDevData->maRecordRect = rRect;
|
|
Paint( rRect );
|
|
mpOutDevData->mpRecordLayout = NULL;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
|
|
void Window::DrawSelectionBackground( const Rectangle& rRect, sal_uInt16 highlight, sal_Bool bChecked, sal_Bool bDrawBorder, sal_Bool bDrawExtBorderOnly )
|
|
{
|
|
DrawSelectionBackground( rRect, highlight, bChecked, bDrawBorder, bDrawExtBorderOnly, 0, NULL, NULL );
|
|
}
|
|
|
|
void Window::DrawSelectionBackground( const Rectangle& rRect, sal_uInt16 highlight, sal_Bool bChecked, sal_Bool bDrawBorder, sal_Bool bDrawExtBorderOnly, Color* pSelectionTextColor )
|
|
{
|
|
DrawSelectionBackground( rRect, highlight, bChecked, bDrawBorder, bDrawExtBorderOnly, 0, pSelectionTextColor, NULL );
|
|
}
|
|
|
|
void Window::DrawSelectionBackground( const Rectangle& rRect,
|
|
sal_uInt16 highlight,
|
|
sal_Bool bChecked,
|
|
sal_Bool bDrawBorder,
|
|
sal_Bool bDrawExtBorderOnly,
|
|
long nCornerRadius,
|
|
Color* pSelectionTextColor,
|
|
Color* pPaintColor
|
|
)
|
|
{
|
|
if( rRect.IsEmpty() )
|
|
return;
|
|
|
|
bool bRoundEdges = nCornerRadius > 0;
|
|
|
|
const StyleSettings& rStyles = GetSettings().GetStyleSettings();
|
|
|
|
|
|
// colors used for item highlighting
|
|
Color aSelectionBorderCol( pPaintColor ? *pPaintColor : rStyles.GetHighlightColor() );
|
|
Color aSelectionFillCol( aSelectionBorderCol );
|
|
|
|
sal_Bool bDark = rStyles.GetFaceColor().IsDark();
|
|
sal_Bool bBright = ( rStyles.GetFaceColor() == Color( COL_WHITE ) );
|
|
|
|
int c1 = aSelectionBorderCol.GetLuminance();
|
|
int c2 = GetDisplayBackground().GetColor().GetLuminance();
|
|
|
|
if( !bDark && !bBright && abs( c2-c1 ) < (pPaintColor ? 40 : 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;
|
|
}
|
|
|
|
if( bRoundEdges )
|
|
{
|
|
if( aSelectionBorderCol.IsDark() )
|
|
aSelectionBorderCol.IncreaseLuminance( 128 );
|
|
else
|
|
aSelectionBorderCol.DecreaseLuminance( 128 );
|
|
}
|
|
|
|
Rectangle aRect( rRect );
|
|
if( bDrawExtBorderOnly )
|
|
{
|
|
--aRect.Left();
|
|
--aRect.Top();
|
|
++aRect.Right();
|
|
++aRect.Bottom();
|
|
}
|
|
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 = bRoundEdges ? 40 : 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 = bRoundEdges ? 60 : 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 )
|
|
}
|
|
}
|
|
|
|
if( bDark && bDrawExtBorderOnly )
|
|
{
|
|
SetFillColor();
|
|
if( pSelectionTextColor )
|
|
*pSelectionTextColor = rStyles.GetHighlightTextColor();
|
|
}
|
|
else
|
|
{
|
|
SetFillColor( aSelectionFillCol );
|
|
if( pSelectionTextColor )
|
|
{
|
|
Color aTextColor = IsControlBackground() ? GetControlForeground() : rStyles.GetButtonTextColor();
|
|
Color aHLTextColor = rStyles.GetHighlightTextColor();
|
|
int nTextDiff = abs(aSelectionFillCol.GetLuminance() - aTextColor.GetLuminance());
|
|
int nHLDiff = abs(aSelectionFillCol.GetLuminance() - aHLTextColor.GetLuminance());
|
|
*pSelectionTextColor = (nHLDiff >= nTextDiff) ? aHLTextColor : aTextColor;
|
|
}
|
|
}
|
|
|
|
|
|
if( bDark )
|
|
{
|
|
DrawRect( aRect );
|
|
}
|
|
else
|
|
{
|
|
if( bRoundEdges )
|
|
{
|
|
Polygon aPoly( aRect, nCornerRadius, nCornerRadius );
|
|
PolyPolygon aPolyPoly( aPoly );
|
|
DrawTransparent( aPolyPoly, nPercent );
|
|
}
|
|
else
|
|
{
|
|
Polygon aPoly( aRect );
|
|
PolyPolygon aPolyPoly( aPoly );
|
|
DrawTransparent( aPolyPoly, nPercent );
|
|
}
|
|
}
|
|
|
|
SetFillColor( oldFillCol );
|
|
SetLineColor( oldLineCol );
|
|
}
|
|
|
|
// controls should return the window that gets the
|
|
// focus by default, so keyevents can be sent to that window directly
|
|
Window* Window::GetPreferredKeyInputWindow()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
|
|
sal_Bool Window::IsScrollable() const
|
|
{
|
|
// check for scrollbars
|
|
Window *pChild = mpWindowImpl->mpFirstChild;
|
|
while( pChild )
|
|
{
|
|
if( pChild->GetType() == WINDOW_SCROLLBAR )
|
|
return true;
|
|
else
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
sal_Bool Window::IsTopWindow() const
|
|
{
|
|
if ( mpWindowImpl->mbInDtor )
|
|
return sal_False;
|
|
|
|
// topwindows must be frames or they must have a borderwindow which is a frame
|
|
if( !mpWindowImpl->mbFrame && (!mpWindowImpl->mpBorderWindow || (mpWindowImpl->mpBorderWindow && !mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) ) )
|
|
return sal_False;
|
|
|
|
ImplGetWinData();
|
|
if( mpWindowImpl->mpWinData->mnIsTopWindow == (sal_uInt16)~0) // still uninitialized
|
|
{
|
|
// #113722#, cache result of expensive queryInterface call
|
|
Window *pThisWin = (Window*)this;
|
|
uno::Reference< XTopWindow > xTopWindow( pThisWin->GetComponentInterface(), UNO_QUERY );
|
|
pThisWin->mpWindowImpl->mpWinData->mnIsTopWindow = xTopWindow.is() ? 1 : 0;
|
|
}
|
|
return mpWindowImpl->mpWinData->mnIsTopWindow == 1 ? sal_True : sal_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)
|
|
sal_Bool Window::IsInModalMode() const
|
|
{
|
|
return (mpWindowImpl->mpFrameWindow->mpWindowImpl->mpFrameData->mnModalMode != 0);
|
|
}
|
|
|
|
bool Window::IsInModalNonRefMode() const
|
|
{
|
|
if(mpWindowImpl->mnStyle & WB_REFMODE)
|
|
return false;
|
|
|
|
return IsInModalMode();
|
|
}
|
|
|
|
void Window::ImplIncModalCount()
|
|
{
|
|
Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
|
|
Window* pParent = pFrameWindow;
|
|
while( pFrameWindow )
|
|
{
|
|
pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode++;
|
|
while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
|
|
{
|
|
pParent = pParent->GetParent();
|
|
}
|
|
pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow : NULL;
|
|
}
|
|
}
|
|
void Window::ImplDecModalCount()
|
|
{
|
|
Window* pFrameWindow = mpWindowImpl->mpFrameWindow;
|
|
Window* pParent = pFrameWindow;
|
|
while( pFrameWindow )
|
|
{
|
|
pFrameWindow->mpWindowImpl->mpFrameData->mnModalMode--;
|
|
while( pParent && pParent->mpWindowImpl->mpFrameWindow == pFrameWindow )
|
|
{
|
|
pParent = pParent->GetParent();
|
|
}
|
|
pFrameWindow = pParent ? pParent->mpWindowImpl->mpFrameWindow : NULL;
|
|
}
|
|
}
|
|
|
|
void Window::ImplIsInTaskPaneList( sal_Bool mbIsInTaskList )
|
|
{
|
|
mpWindowImpl->mbIsInTaskPaneList = mbIsInTaskList;
|
|
}
|
|
|
|
void Window::ImplNotifyIconifiedState( sal_Bool bIconified )
|
|
{
|
|
mpWindowImpl->mpFrameWindow->ImplCallEventListeners( 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->ImplCallEventListeners( bIconified ? VCLEVENT_WINDOW_MINIMIZE : VCLEVENT_WINDOW_NORMALIZE );
|
|
}
|
|
|
|
sal_Bool Window::HasActiveChildFrame()
|
|
{
|
|
sal_Bool bRet = sal_False;
|
|
Window *pFrameWin = ImplGetSVData()->maWinData.mpFirstFrame;
|
|
while( pFrameWin )
|
|
{
|
|
if( pFrameWin != mpWindowImpl->mpFrameWindow )
|
|
{
|
|
sal_Bool bDecorated = sal_False;
|
|
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 = ((FloatingWindow*) pChildFrame)->GetTitleType() != FLOATWIN_TITLE_NONE;
|
|
if( bDecorated || (pFrameWin->mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) ) )
|
|
if( pChildFrame && pChildFrame->IsVisible() && pChildFrame->IsActive() )
|
|
{
|
|
if( ImplIsChild( pChildFrame, sal_True ) )
|
|
{
|
|
bRet = sal_True;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pFrameWin = pFrameWin->mpWindowImpl->mpFrameData->mpNextFrame;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
LanguageType Window::GetInputLanguage() const
|
|
{
|
|
return mpWindowImpl->mpFrame->GetInputLanguage();
|
|
}
|
|
|
|
void Window::EnableNativeWidget( sal_Bool bEnable )
|
|
{
|
|
static const char* pNoNWF = getenv( "SAL_NO_NWF" );
|
|
if( pNoNWF && *pNoNWF )
|
|
bEnable = sal_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( DATACHANGED_SETTINGS, &maSettings, SETTINGS_STYLE );
|
|
DataChanged( 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
|
|
Window *pChild = mpWindowImpl->mpFirstChild;
|
|
while( pChild )
|
|
{
|
|
pChild->EnableNativeWidget( bEnable );
|
|
pChild = pChild->mpWindowImpl->mpNext;
|
|
}
|
|
}
|
|
|
|
sal_Bool Window::IsNativeWidgetEnabled() const
|
|
{
|
|
return ImplGetWinData()->mbEnableNativeWidget;
|
|
}
|
|
|
|
#ifdef WNT // see #140456#
|
|
#include <win/salframe.h>
|
|
#endif
|
|
|
|
uno::Reference< rendering::XCanvas > Window::ImplGetCanvas( const Size& rFullscreenSize,
|
|
bool bFullscreen,
|
|
bool bSpriteCanvas ) const
|
|
{
|
|
// try to retrieve hard reference from weak member
|
|
uno::Reference< 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) );
|
|
|
|
// TODO(Q1): Make GetSystemData method virtual
|
|
|
|
// check whether we're a SysChild: have to fetch system data
|
|
// directly from SystemChildWindow, because the GetSystemData
|
|
// method is unfortunately not virtual
|
|
const SystemChildWindow* pSysChild = dynamic_cast< const SystemChildWindow* >( this );
|
|
if( pSysChild )
|
|
{
|
|
aArg[ 1 ] = pSysChild->GetSystemDataAny();
|
|
aArg[ 5 ] = pSysChild->GetSystemGfxDataAny();
|
|
}
|
|
else
|
|
{
|
|
aArg[ 1 ] = GetSystemDataAny();
|
|
aArg[ 5 ] = GetSystemGfxDataAny();
|
|
}
|
|
|
|
if( bFullscreen )
|
|
aArg[ 2 ] = makeAny( ::com::sun::star::awt::Rectangle( 0, 0,
|
|
rFullscreenSize.Width(),
|
|
rFullscreenSize.Height() ) );
|
|
else
|
|
aArg[ 2 ] = makeAny( ::com::sun::star::awt::Rectangle( mnOutOffX, mnOutOffY, mnOutWidth, mnOutHeight ) );
|
|
|
|
aArg[ 3 ] = makeAny( mpWindowImpl->mbAlwaysOnTop ? sal_True : sal_False );
|
|
aArg[ 4 ] = makeAny( uno::Reference< awt::XWindow >(
|
|
const_cast<Window*>(this)->GetComponentInterface(),
|
|
uno::UNO_QUERY ));
|
|
|
|
uno::Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
|
|
|
|
// Create canvas instance with window handle
|
|
// =========================================
|
|
static ::vcl::DeleteUnoReferenceOnDeinit<lang::XMultiServiceFactory> xStaticCanvasFactory(
|
|
uno::Reference<lang::XMultiServiceFactory>(
|
|
xFactory->createInstance(
|
|
OUString( "com.sun.star.rendering.CanvasFactory" ) ),
|
|
UNO_QUERY ));
|
|
uno::Reference<lang::XMultiServiceFactory> xCanvasFactory(xStaticCanvasFactory.get());
|
|
|
|
if(xCanvasFactory.is())
|
|
{
|
|
#ifdef WNT
|
|
// 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->createInstanceWithArguments(
|
|
bSpriteCanvas ?
|
|
OUString( "com.sun.star.rendering.SpriteCanvas.MultiScreen" ) :
|
|
OUString( "com.sun.star.rendering.Canvas.MultiScreen" ),
|
|
aArg ),
|
|
UNO_QUERY );
|
|
|
|
}
|
|
else
|
|
{
|
|
#endif
|
|
xCanvas.set( xCanvasFactory->createInstanceWithArguments(
|
|
bSpriteCanvas ?
|
|
OUString( "com.sun.star.rendering.SpriteCanvas" ) :
|
|
OUString( "com.sun.star.rendering.Canvas" ),
|
|
aArg ),
|
|
UNO_QUERY );
|
|
|
|
#ifdef WNT
|
|
}
|
|
#endif
|
|
mpWindowImpl->mxCanvas = xCanvas;
|
|
}
|
|
|
|
// no factory??? Empty reference, then.
|
|
return xCanvas;
|
|
}
|
|
|
|
uno::Reference< rendering::XCanvas > Window::GetCanvas() const
|
|
{
|
|
return ImplGetCanvas( Size(), false, false );
|
|
}
|
|
|
|
uno::Reference< rendering::XSpriteCanvas > Window::GetSpriteCanvas() const
|
|
{
|
|
uno::Reference< rendering::XSpriteCanvas > xSpriteCanvas(
|
|
ImplGetCanvas( Size(), false, true ), uno::UNO_QUERY );
|
|
return xSpriteCanvas;
|
|
}
|
|
|
|
void Window::ImplPaintToDevice( OutputDevice* i_pTargetOutDev, const Point& i_rPos )
|
|
{
|
|
sal_Bool bRVisible = mpWindowImpl->mbReallyVisible;
|
|
mpWindowImpl->mbReallyVisible = mpWindowImpl->mbVisible;
|
|
sal_Bool bDevOutput = mbDevOutput;
|
|
mbDevOutput = sal_True;
|
|
|
|
long nOldDPIX = ImplGetDPIX();
|
|
long nOldDPIY = ImplGetDPIY();
|
|
mnDPIX = i_pTargetOutDev->ImplGetDPIX();
|
|
mnDPIY = i_pTargetOutDev->ImplGetDPIY();
|
|
sal_Bool bOutput = IsOutputEnabled();
|
|
EnableOutput();
|
|
|
|
DBG_ASSERT( GetMapMode().GetMapUnit() == MAP_PIXEL, "MapMode must be PIXEL based" );
|
|
if ( GetMapMode().GetMapUnit() != MAP_PIXEL )
|
|
return;
|
|
|
|
// preserve graphicsstate
|
|
Push();
|
|
Region aClipRegion( GetClipRegion() );
|
|
SetClipRegion();
|
|
|
|
GDIMetaFile* pOldMtf = GetConnectMetaFile();
|
|
GDIMetaFile aMtf;
|
|
SetConnectMetaFile( &aMtf );
|
|
|
|
// put a push action to metafile
|
|
Push();
|
|
// copy graphics state to metafile
|
|
Font aCopyFont = GetFont();
|
|
if( nOldDPIX != mnDPIX || nOldDPIY != mnDPIY )
|
|
{
|
|
aCopyFont.SetHeight( aCopyFont.GetHeight() * mnDPIY / nOldDPIY );
|
|
aCopyFont.SetWidth( aCopyFont.GetWidth() * mnDPIX / nOldDPIX );
|
|
}
|
|
SetFont( aCopyFont );
|
|
SetTextColor( GetTextColor() );
|
|
if( IsLineColor() )
|
|
SetLineColor( GetLineColor() );
|
|
else
|
|
SetLineColor();
|
|
if( IsFillColor() )
|
|
SetFillColor( GetFillColor() );
|
|
else
|
|
SetFillColor();
|
|
if( IsTextLineColor() )
|
|
SetTextLineColor( GetTextLineColor() );
|
|
else
|
|
SetTextLineColor();
|
|
if( IsOverlineColor() )
|
|
SetOverlineColor( GetOverlineColor() );
|
|
else
|
|
SetOverlineColor();
|
|
if( IsTextFillColor() )
|
|
SetTextFillColor( GetTextFillColor() );
|
|
else
|
|
SetTextFillColor();
|
|
SetTextAlign( GetTextAlign() );
|
|
SetRasterOp( GetRasterOp() );
|
|
if( IsRefPoint() )
|
|
SetRefPoint( GetRefPoint() );
|
|
else
|
|
SetRefPoint();
|
|
SetLayoutMode( GetLayoutMode() );
|
|
SetDigitLanguage( GetDigitLanguage() );
|
|
Rectangle aPaintRect( Point( 0, 0 ), GetOutputSizePixel() );
|
|
aClipRegion.Intersect( aPaintRect );
|
|
SetClipRegion( aClipRegion );
|
|
|
|
// do the actual paint
|
|
|
|
// background
|
|
if( ! IsPaintTransparent() && IsBackground() && ! (GetParentClipMode() & PARENTCLIPMODE_NOCLIP ) )
|
|
Erase();
|
|
// foreground
|
|
Paint( aPaintRect );
|
|
// put a pop action to metafile
|
|
Pop();
|
|
|
|
SetConnectMetaFile( pOldMtf );
|
|
EnableOutput( bOutput );
|
|
mpWindowImpl->mbReallyVisible = bRVisible;
|
|
|
|
// paint metafile to VDev
|
|
VirtualDevice* pMaskedDevice = new VirtualDevice( *i_pTargetOutDev, 0, 0 );
|
|
pMaskedDevice->SetOutputSizePixel( GetOutputSizePixel() );
|
|
pMaskedDevice->EnableRTL( IsRTLEnabled() );
|
|
aMtf.WindStart();
|
|
aMtf.Play( pMaskedDevice );
|
|
BitmapEx aBmpEx( pMaskedDevice->GetBitmapEx( Point( 0, 0 ), pMaskedDevice->GetOutputSizePixel() ) );
|
|
i_pTargetOutDev->DrawBitmapEx( i_rPos, aBmpEx );
|
|
// get rid of virtual device now so they don't pile up during recursive calls
|
|
delete pMaskedDevice, pMaskedDevice = NULL;
|
|
|
|
|
|
for( Window* pChild = mpWindowImpl->mpFirstChild; pChild; pChild = pChild->mpWindowImpl->mpNext )
|
|
{
|
|
if( pChild->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame && pChild->IsVisible() )
|
|
{
|
|
long nDeltaX = pChild->mnOutOffX - mnOutOffX;
|
|
if( ImplHasMirroredGraphics() )
|
|
nDeltaX = mnOutWidth - nDeltaX - pChild->mnOutWidth;
|
|
long nDeltaY = pChild->GetOutOffYPixel() - GetOutOffYPixel();
|
|
Point aPos( i_rPos );
|
|
Point aDelta( nDeltaX, nDeltaY );
|
|
aPos += aDelta;
|
|
pChild->ImplPaintToDevice( i_pTargetOutDev, aPos );
|
|
}
|
|
}
|
|
|
|
// restore graphics state
|
|
Pop();
|
|
|
|
EnableOutput( bOutput );
|
|
mpWindowImpl->mbReallyVisible = bRVisible;
|
|
mbDevOutput = bDevOutput;
|
|
mnDPIX = nOldDPIX;
|
|
mnDPIY = nOldDPIY;
|
|
}
|
|
|
|
void Window::PaintToDevice( OutputDevice* pDev, const Point& rPos, const Size& /*rSize*/ )
|
|
{
|
|
// FIXME: scaling: currently this is for pixel copying only
|
|
|
|
DBG_ASSERT( ! pDev->ImplHasMirroredGraphics(), "PaintToDevice to mirroring graphics" );
|
|
DBG_ASSERT( ! pDev->IsRTLEnabled(), "PaintToDevice to mirroring device" );
|
|
|
|
Window* pRealParent = NULL;
|
|
if( ! mpWindowImpl->mbVisible )
|
|
{
|
|
Window* pTempParent = ImplGetDefaultWindow();
|
|
if( pTempParent )
|
|
pTempParent->EnableChildTransparentMode();
|
|
pRealParent = GetParent();
|
|
SetParent( pTempParent );
|
|
// trigger correct visibility flags for children
|
|
Show();
|
|
Hide();
|
|
}
|
|
|
|
sal_Bool bVisible = mpWindowImpl->mbVisible;
|
|
mpWindowImpl->mbVisible = sal_True;
|
|
|
|
if( mpWindowImpl->mpBorderWindow )
|
|
mpWindowImpl->mpBorderWindow->ImplPaintToDevice( pDev, rPos );
|
|
else
|
|
ImplPaintToDevice( pDev, rPos );
|
|
|
|
mpWindowImpl->mbVisible = bVisible;
|
|
|
|
if( pRealParent )
|
|
SetParent( pRealParent );
|
|
}
|
|
|
|
rtl::OUString Window::GetSurroundingText() const
|
|
{
|
|
return rtl::OUString();
|
|
}
|
|
|
|
Selection Window::GetSurroundingTextSelection() const
|
|
{
|
|
return Selection( 0, 0 );
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|