df79eedf69
Introduces LevelBar that shares implementation with Progress(Bar). LevelBar is to be as a level indicator, e.g. password strength level. Currently with native backends for gtk and Windows. Currently, except on gtk - the colors of the bar at different levels are hardcoded and not dependent on any kind of themeing. On Windows it follows the styling of progress bar of type "Meter" according to the uxguide: https://learn.microsoft.com/en-us/windows/win32/uxguide/progress-bars#meters Change-Id: Id772cda23615e9582463bf589e4674fd4588c864 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157826 Tested-by: Jenkins Reviewed-by: Sarper Akdemir <sarper.akdemir.extern@allotropia.de>
2624 lines
99 KiB
C++
2624 lines
99 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 <sal/config.h>
|
|
|
|
#include <string_view>
|
|
#include <thread>
|
|
|
|
#ifdef _WIN32
|
|
#include <prewin.h>
|
|
#include <postwin.h>
|
|
#endif
|
|
#include <config_features.h>
|
|
#include <com/sun/star/awt/WindowAttribute.hpp>
|
|
#include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
|
|
#include <com/sun/star/awt/WindowClass.hpp>
|
|
#include <com/sun/star/awt/MessageBoxButtons.hpp>
|
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
|
#include <com/sun/star/lang/SystemDependent.hpp>
|
|
#include <com/sun/star/awt/FocusEvent.hpp>
|
|
#include <com/sun/star/awt/KeyEvent.hpp>
|
|
#include <com/sun/star/awt/KeyModifier.hpp>
|
|
#include <com/sun/star/lang/EventObject.hpp>
|
|
#include <com/sun/star/uno/Reference.hxx>
|
|
#include <com/sun/star/uno/Sequence.hxx>
|
|
#include <com/sun/star/uno/XComponentContext.hpp>
|
|
#include <com/sun/star/uno/XInterface.hpp>
|
|
#include <com/sun/star/beans/NamedValue.hpp>
|
|
#include <com/sun/star/beans/XPropertyChangeListener.hpp>
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
#include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
|
|
#include <com/sun/star/lang/XServiceInfo.hpp>
|
|
#include <com/sun/star/awt/XToolkitExperimental.hpp>
|
|
#include <com/sun/star/awt/XToolkitRobot.hpp>
|
|
|
|
#include <cppuhelper/basemutex.hxx>
|
|
#include <cppuhelper/bootstrap.hxx>
|
|
#include <cppuhelper/compbase.hxx>
|
|
#include <cppuhelper/supportsservice.hxx>
|
|
#include <o3tl/safeint.hxx>
|
|
#include <osl/conditn.hxx>
|
|
#include <osl/module.h>
|
|
#include <osl/thread.hxx>
|
|
#include <osl/mutex.hxx>
|
|
#include <rtl/ref.hxx>
|
|
#include <rtl/process.h>
|
|
#include <sal/log.hxx>
|
|
#include <tools/link.hxx>
|
|
#include <vcl/idletask.hxx>
|
|
#include <vcl/wintypes.hxx>
|
|
|
|
#ifdef MACOSX
|
|
#include <premac.h>
|
|
#include <Cocoa/Cocoa.h>
|
|
#include <postmac.h>
|
|
#endif
|
|
|
|
#include <utility>
|
|
#include <vcl/sysdata.hxx>
|
|
#include <vcl/textrectinfo.hxx>
|
|
#include <vcl/toolkit/vclmedit.hxx>
|
|
|
|
#include <toolkit/awt/vclxwindows.hxx>
|
|
#include <awt/vclxwindows.hxx>
|
|
#include <awt/vclxsystemdependentwindow.hxx>
|
|
#include <awt/vclxregion.hxx>
|
|
#include <awt/vclxtabpagecontainer.hxx>
|
|
#include <awt/vclxtopwindow.hxx>
|
|
|
|
#include <awt/animatedimagespeer.hxx>
|
|
#include <toolkit/awt/vclxwindow.hxx>
|
|
#include <toolkit/helper/vclunohelper.hxx>
|
|
#include <helper/property.hxx>
|
|
|
|
#include <toolkit/helper/convert.hxx>
|
|
#include <controls/filectrl.hxx>
|
|
#include <controls/svmedit.hxx>
|
|
#include <controls/table/tablecontrol.hxx>
|
|
#include <controls/treecontrolpeer.hxx>
|
|
#include <vcl/toolkit/button.hxx>
|
|
#include <vcl/toolkit/calendar.hxx>
|
|
#include <vcl/toolkit/combobox.hxx>
|
|
#include <vcl/ctrl.hxx>
|
|
#include <vcl/toolkit/dialog.hxx>
|
|
#include <vcl/dockingarea.hxx>
|
|
#include <vcl/dockwin.hxx>
|
|
#include <vcl/toolkit/edit.hxx>
|
|
#include <vcl/event.hxx>
|
|
#include <vcl/toolkit/field.hxx>
|
|
#include <vcl/toolkit/fixed.hxx>
|
|
#include <vcl/toolkit/fixedhyper.hxx>
|
|
#include <vcl/toolkit/floatwin.hxx>
|
|
#include <vcl/toolkit/fmtfield.hxx>
|
|
#include <vcl/toolkit/prgsbar.hxx>
|
|
#include <vcl/scheduler.hxx>
|
|
#include <vcl/toolkit/lstbox.hxx>
|
|
#include <vcl/toolkit/longcurr.hxx>
|
|
#include <vcl/toolkit/menubtn.hxx>
|
|
#include <vcl/stdtext.hxx>
|
|
#include <vcl/toolkit/scrbar.hxx>
|
|
#include <vcl/split.hxx>
|
|
#include <vcl/splitwin.hxx>
|
|
#include <vcl/status.hxx>
|
|
#include <vcl/svapp.hxx>
|
|
#include <vcl/syschild.hxx>
|
|
#include <vcl/tabctrl.hxx>
|
|
#include <vcl/tabpage.hxx>
|
|
#include <vcl/toolbox.hxx>
|
|
#include <vcl/virdev.hxx>
|
|
#include <vcl/window.hxx>
|
|
#include <vcl/wrkwin.hxx>
|
|
#include <vcl/toolkit/group.hxx>
|
|
#include <vcl/toolkit/imgctrl.hxx>
|
|
#include <vcl/toolkit/morebtn.hxx>
|
|
#include <vcl/toolkit/roadmap.hxx>
|
|
#include <vcl/toolkit/spin.hxx>
|
|
#include <vcl/toolkit/tabdlg.hxx>
|
|
#include <vcl/toolkit/throbber.hxx>
|
|
#if HAVE_FEATURE_OPENGL
|
|
#include <vcl/opengl/OpenGLWrapper.hxx>
|
|
#endif
|
|
#include <awt/vclxspinbutton.hxx>
|
|
#include <tools/debug.hxx>
|
|
#include <comphelper/diagnose_ex.hxx>
|
|
#include <comphelper/interfacecontainer3.hxx>
|
|
#include <comphelper/processfactory.hxx>
|
|
#include <comphelper/profilezone.hxx>
|
|
|
|
#include <helper/msgbox.hxx>
|
|
#include <helper/scrollabledialog.hxx>
|
|
#include <helper/unowrapper.hxx>
|
|
|
|
#if defined(_WIN32)
|
|
#define SYSTEM_DEPENDENT_TYPE css::lang::SystemDependent::SYSTEM_WIN32
|
|
#elif defined(MACOSX)
|
|
#define SYSTEM_DEPENDENT_TYPE css::lang::SystemDependent::SYSTEM_MAC
|
|
#elif defined(UNX)
|
|
#define SYSTEM_DEPENDENT_TYPE css::lang::SystemDependent::SYSTEM_XWINDOW
|
|
#endif
|
|
|
|
void MessBox::ImplInitButtons()
|
|
{
|
|
ButtonDialogFlags nOKFlags = ButtonDialogFlags::OK;
|
|
ButtonDialogFlags nCancelFlags = ButtonDialogFlags::Cancel;
|
|
ButtonDialogFlags nRetryFlags = ButtonDialogFlags::NONE;
|
|
ButtonDialogFlags nYesFlags = ButtonDialogFlags::NONE;
|
|
ButtonDialogFlags nNoFlags = ButtonDialogFlags::NONE;
|
|
|
|
if ( mnMessBoxStyle & MessBoxStyle::OkCancel )
|
|
{
|
|
if ( mnMessBoxStyle & MessBoxStyle::DefaultCancel )
|
|
nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
else // MessBoxStyle::DefaultOk
|
|
nOKFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
|
|
AddButton( StandardButtonType::OK, RET_OK, nOKFlags );
|
|
AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags );
|
|
}
|
|
else if ( mnMessBoxStyle & MessBoxStyle::YesNo )
|
|
{
|
|
if ( mnMessBoxStyle & MessBoxStyle::DefaultYes )
|
|
nYesFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
else // MessBoxStyle::DefaultNo
|
|
nNoFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
nNoFlags |= ButtonDialogFlags::Cancel;
|
|
|
|
AddButton( StandardButtonType::Yes, RET_YES, nYesFlags );
|
|
AddButton( StandardButtonType::No, RET_NO, nNoFlags );
|
|
}
|
|
else if ( mnMessBoxStyle & MessBoxStyle::YesNoCancel )
|
|
{
|
|
if ( mnMessBoxStyle & MessBoxStyle::DefaultYes )
|
|
nYesFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
else if ( mnMessBoxStyle & MessBoxStyle::DefaultNo )
|
|
nNoFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
else
|
|
nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
|
|
AddButton( StandardButtonType::Yes, RET_YES, nYesFlags );
|
|
AddButton( StandardButtonType::No, RET_NO, nNoFlags );
|
|
AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags );
|
|
}
|
|
else if ( mnMessBoxStyle & MessBoxStyle::RetryCancel )
|
|
{
|
|
if ( mnMessBoxStyle & MessBoxStyle::DefaultCancel )
|
|
nCancelFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
else // MessBoxStyle::DefaultRetry
|
|
nRetryFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
|
|
AddButton( StandardButtonType::Retry, RET_RETRY, nRetryFlags );
|
|
AddButton( StandardButtonType::Cancel, RET_CANCEL, nCancelFlags );
|
|
}
|
|
else if ( mnMessBoxStyle & MessBoxStyle::AbortRetryIgnore )
|
|
{
|
|
ButtonDialogFlags nAbortFlags = ButtonDialogFlags::NONE;
|
|
ButtonDialogFlags nIgnoreFlags = ButtonDialogFlags::NONE;
|
|
|
|
if ( mnMessBoxStyle & MessBoxStyle::DefaultCancel )
|
|
nAbortFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
else if ( mnMessBoxStyle & MessBoxStyle::DefaultRetry )
|
|
nRetryFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
else if ( mnMessBoxStyle & MessBoxStyle::DefaultIgnore )
|
|
nIgnoreFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
|
|
AddButton( StandardButtonType::Abort, RET_CANCEL, nAbortFlags );
|
|
AddButton( StandardButtonType::Retry, RET_RETRY, nRetryFlags );
|
|
AddButton( StandardButtonType::Ignore, RET_IGNORE, nIgnoreFlags );
|
|
}
|
|
else if ( mnMessBoxStyle & MessBoxStyle::Ok )
|
|
{
|
|
nOKFlags |= ButtonDialogFlags::Default | ButtonDialogFlags::Focus;
|
|
|
|
AddButton( StandardButtonType::OK, RET_OK, nOKFlags );
|
|
}
|
|
}
|
|
|
|
MessBox::MessBox(vcl::Window* pParent, MessBoxStyle nMessBoxStyle, WinBits nWinBits,
|
|
const OUString& rTitle, OUString aMessage) :
|
|
ButtonDialog( WindowType::MESSBOX ),
|
|
mbHelpBtn( false ),
|
|
mnMessBoxStyle( nMessBoxStyle ),
|
|
maMessText(std::move( aMessage ))
|
|
{
|
|
ImplLOKNotifier(pParent);
|
|
ImplInitDialog(pParent, nWinBits | WB_MOVEABLE | WB_HORZ | WB_CENTER);
|
|
ImplInitButtons();
|
|
|
|
if ( !rTitle.isEmpty() )
|
|
SetText( rTitle );
|
|
}
|
|
|
|
MessBox::~MessBox()
|
|
{
|
|
disposeOnce();
|
|
}
|
|
|
|
void MessBox::dispose()
|
|
{
|
|
mpVCLMultiLineEdit.disposeAndClear();
|
|
mpFixedImage.disposeAndClear();
|
|
ButtonDialog::dispose();
|
|
}
|
|
|
|
void MessBox::ImplPosControls()
|
|
{
|
|
if ( !GetHelpId().isEmpty() )
|
|
{
|
|
if ( !mbHelpBtn )
|
|
{
|
|
AddButton( StandardButtonType::Help, RET_HELP, ButtonDialogFlags::Help, 3 );
|
|
mbHelpBtn = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( mbHelpBtn )
|
|
{
|
|
RemoveButton( RET_HELP );
|
|
mbHelpBtn = false;
|
|
}
|
|
}
|
|
|
|
TextRectInfo aTextInfo;
|
|
tools::Rectangle aRect( 0, 0, 30000, 30000 );
|
|
tools::Rectangle aFormatRect;
|
|
Point aTextPos( IMPL_DIALOG_OFFSET, IMPL_DIALOG_OFFSET+IMPL_MSGBOX_OFFSET_EXTRA_Y );
|
|
Size aImageSize;
|
|
Size aPageSize;
|
|
Size aMEditSize;
|
|
tools::Long nTitleWidth;
|
|
tools::Long nButtonSize = ImplGetButtonSize();
|
|
tools::Long nMaxLineWidth;
|
|
tools::Long nWidth;
|
|
WinBits nWinStyle = WB_LEFT | WB_NOLABEL;
|
|
DrawTextFlags nTextStyle = DrawTextFlags::MultiLine | DrawTextFlags::Top | DrawTextFlags::Left;
|
|
|
|
mpVCLMultiLineEdit.disposeAndClear();
|
|
mpFixedImage.disposeAndClear();
|
|
|
|
// Clean up message text with tabs
|
|
OUString aMessText(maMessText.replaceAll("\t", " "));
|
|
|
|
//If window too small, we make dialog box be wider
|
|
tools::Long nMaxWidth = 630 * GetDPIScaleFactor();
|
|
|
|
// MessagBox should be at least as wide as to see the title
|
|
// Extra-Width for Close button, because Close button is set after this call
|
|
nTitleWidth = CalcTitleWidth();
|
|
|
|
nMaxWidth -= (IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2);
|
|
|
|
// for an image, get its size, create a suitable control and position it
|
|
aImageSize = maImage.GetSizePixel();
|
|
if ( aImageSize.Width() )
|
|
{
|
|
aImageSize.AdjustWidth(4 );
|
|
aImageSize.AdjustHeight(4 );
|
|
aTextPos.AdjustX(aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE );
|
|
mpFixedImage = VclPtr<FixedImage>::Create( this );
|
|
mpFixedImage->SetPosSizePixel( Point( IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_X,
|
|
IMPL_DIALOG_OFFSET-2+IMPL_MSGBOX_OFFSET_EXTRA_Y ),
|
|
aImageSize );
|
|
mpFixedImage->SetImage( maImage );
|
|
mpFixedImage->Show();
|
|
nMaxWidth -= aImageSize.Width()+IMPL_SEP_MSGBOX_IMAGE;
|
|
}
|
|
else
|
|
aTextPos.AdjustX(IMPL_MSGBOX_OFFSET_EXTRA_X );
|
|
|
|
// Determine maximum line length without wordbreak
|
|
aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
|
|
nMaxLineWidth = aFormatRect.GetWidth();
|
|
nTextStyle |= DrawTextFlags::WordBreak;
|
|
|
|
// Determine the width for text formatting
|
|
if ( nMaxLineWidth > 450 )
|
|
nWidth = 450;
|
|
else if ( nMaxLineWidth > 300 )
|
|
nWidth = nMaxLineWidth+5;
|
|
else
|
|
nWidth = 300;
|
|
|
|
nWidth *= GetDPIScaleFactor();
|
|
|
|
if ( nButtonSize > nWidth )
|
|
nWidth = nButtonSize-(aTextPos.X()-IMPL_DIALOG_OFFSET);
|
|
if ( nWidth > nMaxWidth )
|
|
nWidth = nMaxWidth;
|
|
|
|
aRect.SetRight( nWidth );
|
|
aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
|
|
if ( aTextInfo.GetMaxLineWidth() > nWidth )
|
|
{
|
|
nWidth = aTextInfo.GetMaxLineWidth()+8;
|
|
aRect.SetRight( nWidth );
|
|
aFormatRect = GetTextRect( aRect, aMessText, nTextStyle, &aTextInfo );
|
|
}
|
|
|
|
// get Style for VCLMultiLineEdit
|
|
aMEditSize.setWidth( aTextInfo.GetMaxLineWidth()+1 );
|
|
aMEditSize.setHeight( aFormatRect.GetHeight() );
|
|
aPageSize.setWidth( aImageSize.Width() );
|
|
if ( aMEditSize.Height() < aImageSize.Height() )
|
|
{
|
|
nWinStyle |= WB_VCENTER;
|
|
aPageSize.setHeight( aImageSize.Height() );
|
|
aMEditSize.setHeight( aImageSize.Height() );
|
|
}
|
|
else
|
|
{
|
|
nWinStyle |= WB_TOP;
|
|
aPageSize.setHeight( aMEditSize.Height() );
|
|
}
|
|
if ( aImageSize.Width() )
|
|
aPageSize.AdjustWidth(IMPL_SEP_MSGBOX_IMAGE );
|
|
aPageSize.AdjustWidth((IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_X*2) );
|
|
aPageSize.AdjustWidth(aMEditSize.Width()+1 );
|
|
aPageSize.AdjustHeight((IMPL_DIALOG_OFFSET*2)+(IMPL_MSGBOX_OFFSET_EXTRA_Y*2) );
|
|
|
|
if ( aPageSize.Width() < IMPL_MINSIZE_MSGBOX_WIDTH )
|
|
aPageSize.setWidth( IMPL_MINSIZE_MSGBOX_WIDTH );
|
|
if ( aPageSize.Width() < nTitleWidth )
|
|
aPageSize.setWidth( nTitleWidth );
|
|
|
|
mpVCLMultiLineEdit = VclPtr<VclMultiLineEdit>::Create( this, nWinStyle );
|
|
mpVCLMultiLineEdit->SetText( aMessText );
|
|
mpVCLMultiLineEdit->SetPosSizePixel( aTextPos, aMEditSize );
|
|
mpVCLMultiLineEdit->Show();
|
|
mpVCLMultiLineEdit->SetPaintTransparent(true);
|
|
mpVCLMultiLineEdit->EnableCursor(false);
|
|
SetPageSizePixel( aPageSize );
|
|
}
|
|
|
|
void MessBox::StateChanged( StateChangedType nType )
|
|
{
|
|
if ( nType == StateChangedType::InitShow )
|
|
{
|
|
ImplPosControls();
|
|
}
|
|
ButtonDialog::StateChanged( nType );
|
|
}
|
|
|
|
Size MessBox::GetOptimalSize() const
|
|
{
|
|
// FIXME: base me on the font size ?
|
|
return Size( 250, 100 );
|
|
}
|
|
|
|
|
|
namespace {
|
|
|
|
class Pause : public Idle
|
|
{
|
|
public:
|
|
explicit Pause(sal_Int32 nPauseMilliseconds) :
|
|
Idle("pause"),
|
|
m_nPauseMilliseconds(nPauseMilliseconds)
|
|
{
|
|
SetPriority(TaskPriority::HIGHEST);
|
|
Start();
|
|
}
|
|
|
|
virtual void Invoke() override
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(m_nPauseMilliseconds));
|
|
Stop();
|
|
delete this;
|
|
}
|
|
|
|
sal_Int32 m_nPauseMilliseconds;
|
|
};
|
|
|
|
class VCLXToolkit : public cppu::BaseMutex,
|
|
public cppu::WeakComponentImplHelper<
|
|
css::awt::XToolkitExperimental,
|
|
css::awt::XToolkitRobot,
|
|
css::lang::XServiceInfo >
|
|
{
|
|
css::uno::Reference< css::datatransfer::clipboard::XClipboard > mxClipboard;
|
|
css::uno::Reference< css::datatransfer::clipboard::XClipboard > mxSelection;
|
|
|
|
::comphelper::OInterfaceContainerHelper3<css::awt::XTopWindowListener> m_aTopWindowListeners;
|
|
::comphelper::OInterfaceContainerHelper3<css::awt::XKeyHandler> m_aKeyHandlers;
|
|
::comphelper::OInterfaceContainerHelper3<css::awt::XFocusListener> m_aFocusListeners;
|
|
::Link<VclSimpleEvent&,void> m_aEventListenerLink;
|
|
::Link<VclWindowEvent&,bool> m_aKeyListenerLink;
|
|
bool m_bEventListener;
|
|
bool m_bKeyListener;
|
|
|
|
DECL_LINK(eventListenerHandler, ::VclSimpleEvent&, void);
|
|
|
|
DECL_LINK(keyListenerHandler, ::VclWindowEvent&, bool);
|
|
|
|
void callTopWindowListeners(
|
|
::VclSimpleEvent const * pEvent,
|
|
void (SAL_CALL css::awt::XTopWindowListener::* pFn)(
|
|
css::lang::EventObject const &));
|
|
|
|
bool callKeyHandlers(::VclSimpleEvent const * pEvent, bool bPressed);
|
|
|
|
void callFocusListeners(::VclSimpleEvent const * pEvent, bool bGained);
|
|
|
|
protected:
|
|
::osl::Mutex& GetMutex() { return m_aMutex; }
|
|
|
|
virtual void SAL_CALL disposing() override;
|
|
|
|
static vcl::Window* ImplCreateWindow( rtl::Reference<VCLXWindow>* ppNewComp, const css::awt::WindowDescriptor& rDescriptor, vcl::Window* pParent,
|
|
WinBits nWinBits, MessBoxStyle nMessBoxStyle );
|
|
css::uno::Reference< css::awt::XWindowPeer > ImplCreateWindow( const css::awt::WindowDescriptor& Descriptor,
|
|
MessBoxStyle nForceMessBoxStyle );
|
|
|
|
public:
|
|
|
|
VCLXToolkit();
|
|
|
|
// css::awt::XToolkitExperimental
|
|
virtual void SAL_CALL processEventsToIdle() override;
|
|
|
|
virtual sal_Int64 SAL_CALL getOpenGLBufferSwapCounter() override;
|
|
|
|
virtual void SAL_CALL setDeterministicScheduling(sal_Bool bDeterministicMode) override;
|
|
|
|
virtual void SAL_CALL pause(sal_Int32 nMilliseconds) override;
|
|
|
|
virtual void SAL_CALL startRecording() override;
|
|
|
|
virtual void SAL_CALL stopRecording() override;
|
|
|
|
css::uno::Sequence< OUString > SAL_CALL getRecordingAndClear() override;
|
|
|
|
virtual void SAL_CALL waitUntilAllIdlesDispatched() override;
|
|
|
|
// css::awt::XToolkit
|
|
css::uno::Reference< css::awt::XWindowPeer > SAL_CALL getDesktopWindow( ) override;
|
|
css::awt::Rectangle SAL_CALL getWorkArea( ) override;
|
|
css::uno::Reference< css::awt::XWindowPeer > SAL_CALL createWindow( const css::awt::WindowDescriptor& Descriptor ) override;
|
|
css::uno::Sequence< css::uno::Reference< css::awt::XWindowPeer > > SAL_CALL createWindows( const css::uno::Sequence< css::awt::WindowDescriptor >& Descriptors ) override;
|
|
css::uno::Reference< css::awt::XDevice > SAL_CALL createScreenCompatibleDevice( sal_Int32 Width, sal_Int32 Height ) override;
|
|
css::uno::Reference< css::awt::XRegion > SAL_CALL createRegion( ) override;
|
|
|
|
// css::awt::XSystemChildFactory
|
|
css::uno::Reference< css::awt::XWindowPeer > SAL_CALL createSystemChild( const css::uno::Any& Parent, const css::uno::Sequence< sal_Int8 >& ProcessId, sal_Int16 SystemType ) override;
|
|
|
|
// css::awt::XMessageBoxFactory
|
|
virtual css::uno::Reference< css::awt::XMessageBox > SAL_CALL createMessageBox( const css::uno::Reference< css::awt::XWindowPeer >& aParent, css::awt::MessageBoxType eType, ::sal_Int32 aButtons, const OUString& aTitle, const OUString& aMessage ) override;
|
|
|
|
// css::awt::XDataTransfer
|
|
css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > SAL_CALL getDragGestureRecognizer( const css::uno::Reference< css::awt::XWindow >& window ) override;
|
|
css::uno::Reference< css::datatransfer::dnd::XDragSource > SAL_CALL getDragSource( const css::uno::Reference< css::awt::XWindow >& window ) override;
|
|
css::uno::Reference< css::datatransfer::dnd::XDropTarget > SAL_CALL getDropTarget( const css::uno::Reference< css::awt::XWindow >& window ) override;
|
|
css::uno::Reference< css::datatransfer::clipboard::XClipboard > SAL_CALL getClipboard( const OUString& clipboardName ) override;
|
|
|
|
// css::lang::XServiceInfo
|
|
OUString SAL_CALL getImplementationName( ) override;
|
|
sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
|
|
css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
|
|
|
|
// css::awt::XExtendedToolkit:
|
|
|
|
virtual ::sal_Int32 SAL_CALL getTopWindowCount() override;
|
|
|
|
virtual css::uno::Reference< css::awt::XTopWindow >
|
|
SAL_CALL getTopWindow(::sal_Int32 nIndex) override;
|
|
|
|
virtual css::uno::Reference< css::awt::XTopWindow >
|
|
SAL_CALL getActiveTopWindow() override;
|
|
|
|
virtual void SAL_CALL addTopWindowListener(
|
|
css::uno::Reference<
|
|
css::awt::XTopWindowListener > const & rListener) override;
|
|
|
|
virtual void SAL_CALL removeTopWindowListener(
|
|
css::uno::Reference<
|
|
css::awt::XTopWindowListener > const & rListener) override;
|
|
|
|
virtual void SAL_CALL addKeyHandler(
|
|
css::uno::Reference<
|
|
css::awt::XKeyHandler > const & rHandler) override;
|
|
|
|
virtual void SAL_CALL removeKeyHandler(
|
|
css::uno::Reference<
|
|
css::awt::XKeyHandler > const & rHandler) override;
|
|
|
|
virtual void SAL_CALL addFocusListener(
|
|
css::uno::Reference<
|
|
css::awt::XFocusListener > const & rListener) override;
|
|
|
|
virtual void SAL_CALL removeFocusListener(
|
|
css::uno::Reference<
|
|
css::awt::XFocusListener > const & rListener) override;
|
|
|
|
virtual void SAL_CALL fireFocusGained(
|
|
css::uno::Reference<
|
|
css::uno::XInterface > const & source) override;
|
|
|
|
virtual void SAL_CALL fireFocusLost(
|
|
css::uno::Reference<
|
|
css::uno::XInterface > const & source) override;
|
|
|
|
// css::awt::XReschedule:
|
|
virtual void SAL_CALL reschedule() override;
|
|
|
|
// css::awt::XFontMappingUse:
|
|
virtual void SAL_CALL startTrackingFontMappingUse() override;
|
|
|
|
virtual css::uno::Sequence<css::awt::XFontMappingUseItem> SAL_CALL finishTrackingFontMappingUse() override;
|
|
|
|
// css:awt:XToolkitRobot
|
|
virtual void SAL_CALL keyPress( const css::awt::KeyEvent & aKeyEvent ) override;
|
|
|
|
virtual void SAL_CALL keyRelease( const css::awt::KeyEvent & aKeyEvent ) override;
|
|
|
|
virtual void SAL_CALL mousePress( const css::awt::MouseEvent & aMouseEvent ) override;
|
|
|
|
virtual void SAL_CALL mouseRelease( const css::awt::MouseEvent & aMouseEvent ) override;
|
|
|
|
virtual void SAL_CALL mouseMove( const css::awt::MouseEvent & aMouseEvent ) override;
|
|
|
|
};
|
|
|
|
std::pair<WinBits,MessBoxStyle> ImplGetWinBits( sal_uInt32 nComponentAttribs, WindowType nCompType )
|
|
{
|
|
WinBits nWinBits = 0;
|
|
MessBoxStyle nStyle = MessBoxStyle::NONE;
|
|
|
|
bool bMessBox = false;
|
|
if ( ( nCompType == WindowType::INFOBOX ) ||
|
|
( nCompType == WindowType::MESSBOX ) ||
|
|
( nCompType == WindowType::QUERYBOX ) ||
|
|
( nCompType == WindowType::WARNINGBOX ) ||
|
|
( nCompType == WindowType::ERRORBOX ) )
|
|
{
|
|
bMessBox = true;
|
|
}
|
|
|
|
bool bDecoratedWindow = false;
|
|
if ( bMessBox
|
|
|| ( nCompType == WindowType::DIALOG )
|
|
|| ( nCompType == WindowType::MODELESSDIALOG )
|
|
|| ( nCompType == WindowType::DOCKINGWINDOW )
|
|
|| ( nCompType == WindowType::TABDIALOG )
|
|
|| ( nCompType == WindowType::BUTTONDIALOG )
|
|
|| ( nCompType == WindowType::SYSTEMCHILDWINDOW )
|
|
)
|
|
{
|
|
bDecoratedWindow = true;
|
|
}
|
|
|
|
if( nComponentAttribs & css::awt::WindowAttribute::BORDER )
|
|
nWinBits |= WB_BORDER;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::NOBORDER )
|
|
nWinBits |= WB_NOBORDER;
|
|
if( nComponentAttribs & css::awt::WindowAttribute::SIZEABLE )
|
|
nWinBits |= WB_SIZEABLE;
|
|
if( nComponentAttribs & css::awt::WindowAttribute::MOVEABLE )
|
|
nWinBits |= WB_MOVEABLE;
|
|
if( nComponentAttribs & css::awt::WindowAttribute::CLOSEABLE )
|
|
nWinBits |= WB_CLOSEABLE;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::HSCROLL )
|
|
nWinBits |= WB_HSCROLL;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::VSCROLL )
|
|
nWinBits |= WB_VSCROLL;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::LEFT )
|
|
nWinBits |= WB_LEFT;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::CENTER )
|
|
nWinBits |= WB_CENTER;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::RIGHT )
|
|
nWinBits |= WB_RIGHT;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::SPIN )
|
|
nWinBits |= WB_SPIN;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::SORT )
|
|
nWinBits |= WB_SORT;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DROPDOWN )
|
|
nWinBits |= WB_DROPDOWN;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEFBUTTON )
|
|
nWinBits |= WB_DEFBUTTON;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::READONLY )
|
|
nWinBits |= WB_READONLY;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::CLIPCHILDREN )
|
|
nWinBits |= WB_CLIPCHILDREN;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::GROUP )
|
|
nWinBits |= WB_GROUP;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::NOLABEL ) //added for issue79712
|
|
nWinBits |= WB_NOLABEL;
|
|
|
|
// These bits are not unique
|
|
if ( bMessBox )
|
|
{
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::OK )
|
|
nStyle |= MessBoxStyle::Ok;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::OK_CANCEL )
|
|
nStyle |= MessBoxStyle::OkCancel;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::YES_NO )
|
|
nStyle |= MessBoxStyle::YesNo;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::YES_NO_CANCEL )
|
|
nStyle |= MessBoxStyle::YesNoCancel;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::RETRY_CANCEL )
|
|
nStyle |= MessBoxStyle::RetryCancel;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_OK )
|
|
nStyle |= MessBoxStyle::DefaultOk;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_CANCEL )
|
|
nStyle |= MessBoxStyle::DefaultCancel;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_RETRY )
|
|
nStyle |= MessBoxStyle::DefaultRetry;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_YES )
|
|
nStyle |= MessBoxStyle::DefaultYes;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::DEF_NO )
|
|
nStyle |= MessBoxStyle::DefaultNo;
|
|
}
|
|
if ( nCompType == WindowType::MULTILINEEDIT || nCompType == WindowType::DIALOG
|
|
|| nCompType == WindowType::GROUPBOX || nCompType == WindowType::TABPAGE )
|
|
{
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::AUTOHSCROLL )
|
|
nWinBits |= WB_AUTOHSCROLL;
|
|
if( nComponentAttribs & css::awt::VclWindowPeerAttribute::AUTOVSCROLL )
|
|
nWinBits |= WB_AUTOVSCROLL;
|
|
}
|
|
|
|
|
|
if ( bDecoratedWindow )
|
|
{
|
|
if( nComponentAttribs & css::awt::WindowAttribute::NODECORATION )
|
|
{
|
|
// No decoration removes several window attributes and must
|
|
// set WB_NOBORDER!
|
|
nWinBits &= ~WB_BORDER;
|
|
nWinBits &= ~WB_SIZEABLE;
|
|
nWinBits &= ~WB_MOVEABLE;
|
|
nWinBits &= ~WB_CLOSEABLE;
|
|
nWinBits |= WB_NOBORDER;
|
|
}
|
|
}
|
|
|
|
return { nWinBits, nStyle };
|
|
}
|
|
|
|
struct ComponentInfo
|
|
{
|
|
std::u16string_view sName;
|
|
WindowType nWinType;
|
|
};
|
|
|
|
ComponentInfo const aComponentInfos [] =
|
|
{
|
|
{ std::u16string_view(u"animatedimages"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"buttondialog"), WindowType::BUTTONDIALOG },
|
|
{ std::u16string_view(u"cancelbutton"), WindowType::CANCELBUTTON },
|
|
{ std::u16string_view(u"checkbox"), WindowType::CHECKBOX },
|
|
{ std::u16string_view(u"combobox"), WindowType::COMBOBOX },
|
|
{ std::u16string_view(u"control"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"currencybox"), WindowType::CURRENCYBOX },
|
|
{ std::u16string_view(u"currencyfield"), WindowType::CURRENCYFIELD },
|
|
{ std::u16string_view(u"datebox"), WindowType::DATEBOX },
|
|
{ std::u16string_view(u"datefield"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"dialog"), WindowType::DIALOG },
|
|
{ std::u16string_view(u"dockingarea"), WindowType::DOCKINGAREA },
|
|
{ std::u16string_view(u"dockingwindow"), WindowType::DOCKINGWINDOW },
|
|
{ std::u16string_view(u"edit"), WindowType::EDIT },
|
|
{ std::u16string_view(u"errorbox"), WindowType::ERRORBOX },
|
|
{ std::u16string_view(u"filecontrol"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"fixedbitmap"), WindowType::FIXEDBITMAP },
|
|
{ std::u16string_view(u"fixedhyperlink"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"fixedimage"), WindowType::FIXEDIMAGE },
|
|
{ std::u16string_view(u"fixedline"), WindowType::FIXEDLINE },
|
|
{ std::u16string_view(u"fixedtext"), WindowType::FIXEDTEXT },
|
|
{ std::u16string_view(u"floatingwindow"), WindowType::FLOATINGWINDOW },
|
|
{ std::u16string_view(u"formattedfield"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"frame"), WindowType::GROUPBOX },
|
|
{ std::u16string_view(u"framewindow"), WindowType::TOOLKIT_FRAMEWINDOW },
|
|
{ std::u16string_view(u"grid"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"groupbox"), WindowType::GROUPBOX },
|
|
{ std::u16string_view(u"helpbutton"), WindowType::HELPBUTTON },
|
|
{ std::u16string_view(u"imagebutton"), WindowType::IMAGEBUTTON },
|
|
{ std::u16string_view(u"infobox"), WindowType::INFOBOX },
|
|
{ std::u16string_view(u"listbox"), WindowType::LISTBOX },
|
|
{ std::u16string_view(u"longcurrencybox"), WindowType::LONGCURRENCYBOX },
|
|
{ std::u16string_view(u"longcurrencyfield"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"menubutton"), WindowType::MENUBUTTON },
|
|
{ std::u16string_view(u"messbox"), WindowType::MESSBOX },
|
|
{ std::u16string_view(u"metricbox"), WindowType::METRICBOX },
|
|
{ std::u16string_view(u"metricfield"), WindowType::METRICFIELD },
|
|
{ std::u16string_view(u"modelessdialog"), WindowType::MODELESSDIALOG },
|
|
{ std::u16string_view(u"morebutton"), WindowType::MOREBUTTON },
|
|
{ std::u16string_view(u"multilineedit"), WindowType::MULTILINEEDIT },
|
|
{ std::u16string_view(u"multilistbox"), WindowType::MULTILISTBOX },
|
|
{ std::u16string_view(u"numericbox"), WindowType::NUMERICBOX },
|
|
{ std::u16string_view(u"numericfield"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"okbutton"), WindowType::OKBUTTON },
|
|
{ std::u16string_view(u"patternbox"), WindowType::PATTERNBOX },
|
|
{ std::u16string_view(u"patternfield"), WindowType::PATTERNFIELD },
|
|
{ std::u16string_view(u"progressbar"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"pushbutton"), WindowType::PUSHBUTTON },
|
|
{ std::u16string_view(u"querybox"), WindowType::QUERYBOX },
|
|
{ std::u16string_view(u"radiobutton"), WindowType::RADIOBUTTON },
|
|
{ std::u16string_view(u"roadmap"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"scrollbar"), WindowType::SCROLLBAR },
|
|
{ std::u16string_view(u"scrollbarbox"), WindowType::SCROLLBARBOX },
|
|
{ std::u16string_view(u"spinbutton"), WindowType::SPINBUTTON },
|
|
{ std::u16string_view(u"spinfield"), WindowType::SPINFIELD },
|
|
{ std::u16string_view(u"splitter"), WindowType::SPLITTER },
|
|
{ std::u16string_view(u"splitwindow"), WindowType::SPLITWINDOW },
|
|
{ std::u16string_view(u"statusbar"), WindowType::STATUSBAR },
|
|
{ std::u16string_view(u"systemchildwindow"), WindowType::TOOLKIT_SYSTEMCHILDWINDOW },
|
|
{ std::u16string_view(u"tabcontrol"), WindowType::TABCONTROL },
|
|
{ std::u16string_view(u"tabdialog"), WindowType::TABDIALOG },
|
|
{ std::u16string_view(u"tabpage"), WindowType::TABPAGE },
|
|
{ std::u16string_view(u"tabpagecontainer"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"tabpagemodel"), WindowType::TABPAGE },
|
|
{ std::u16string_view(u"timebox"), WindowType::TIMEBOX },
|
|
{ std::u16string_view(u"timefield"), WindowType::TIMEFIELD },
|
|
{ std::u16string_view(u"toolbox"), WindowType::TOOLBOX },
|
|
{ std::u16string_view(u"tree"), WindowType::CONTROL },
|
|
{ std::u16string_view(u"tristatebox"), WindowType::TRISTATEBOX },
|
|
{ std::u16string_view(u"warningbox"), WindowType::WARNINGBOX },
|
|
{ std::u16string_view(u"window"), WindowType::WINDOW },
|
|
{ std::u16string_view(u"workwindow"), WindowType::WORKWINDOW }
|
|
};
|
|
|
|
bool ComponentInfoFindCompare( const ComponentInfo & lhs, const OUString & s)
|
|
{
|
|
return rtl_ustr_compareIgnoreAsciiCase_WithLength(s.pData->buffer, s.pData->length,
|
|
lhs.sName.data(), lhs.sName.size()) > 0;
|
|
}
|
|
|
|
WindowType ImplGetComponentType( const OUString& rServiceName )
|
|
{
|
|
static bool bSorted = false;
|
|
if( !bSorted )
|
|
{
|
|
assert( std::is_sorted( std::begin(aComponentInfos), std::end(aComponentInfos),
|
|
[](const ComponentInfo & lhs, const ComponentInfo & rhs) {
|
|
return
|
|
rtl_ustr_compare_WithLength(
|
|
lhs.sName.data(), lhs.sName.size(), rhs.sName.data(),
|
|
rhs.sName.size())
|
|
< 0;
|
|
} ) );
|
|
bSorted = true;
|
|
}
|
|
|
|
OUString sSearch;
|
|
if ( !rServiceName.isEmpty() )
|
|
sSearch = rServiceName;
|
|
else
|
|
sSearch = "window";
|
|
|
|
auto it = std::lower_bound( std::begin(aComponentInfos), std::end(aComponentInfos), sSearch,
|
|
ComponentInfoFindCompare );
|
|
if (it != std::end(aComponentInfos) &&
|
|
rtl_ustr_compareIgnoreAsciiCase_WithLength(sSearch.pData->buffer, sSearch.pData->length, it->sName.data(), it->sName.size()) == 0)
|
|
return it->nWinType;
|
|
return WindowType::NONE;
|
|
}
|
|
|
|
struct MessageBoxTypeInfo
|
|
{
|
|
css::awt::MessageBoxType eType;
|
|
const char *pName;
|
|
sal_Int32 nLen;
|
|
};
|
|
|
|
const MessageBoxTypeInfo aMessageBoxTypeInfo[] =
|
|
{
|
|
{ css::awt::MessageBoxType_MESSAGEBOX, RTL_CONSTASCII_STRINGPARAM("messbox") },
|
|
{ css::awt::MessageBoxType_INFOBOX, RTL_CONSTASCII_STRINGPARAM("infobox") },
|
|
{ css::awt::MessageBoxType_WARNINGBOX, RTL_CONSTASCII_STRINGPARAM("warningbox") },
|
|
{ css::awt::MessageBoxType_ERRORBOX, RTL_CONSTASCII_STRINGPARAM("errorbox") },
|
|
{ css::awt::MessageBoxType_QUERYBOX, RTL_CONSTASCII_STRINGPARAM("querybox") },
|
|
{ css::awt::MessageBoxType::MessageBoxType_MAKE_FIXED_SIZE, nullptr, 0 }
|
|
};
|
|
|
|
bool lcl_convertMessageBoxType(
|
|
OUString &sType,
|
|
css::awt::MessageBoxType eType )
|
|
{
|
|
const MessageBoxTypeInfo *pMap = aMessageBoxTypeInfo;
|
|
css::awt::MessageBoxType eVal = css::awt::MessageBoxType::MessageBoxType_MAKE_FIXED_SIZE;
|
|
|
|
while ( pMap->pName )
|
|
{
|
|
if ( pMap->eType == eType )
|
|
{
|
|
eVal = eType;
|
|
sType = OUString( pMap->pName, pMap->nLen, RTL_TEXTENCODING_ASCII_US );
|
|
break;
|
|
}
|
|
pMap++;
|
|
}
|
|
|
|
return ( eVal != css::awt::MessageBoxType::MessageBoxType_MAKE_FIXED_SIZE );
|
|
}
|
|
|
|
#ifndef IOS
|
|
|
|
sal_Int32 nVCLToolkitInstanceCount = 0;
|
|
bool bInitedByVCLToolkit = false;
|
|
|
|
osl::Mutex & getInitMutex()
|
|
{
|
|
static osl::Mutex aMutex;
|
|
return aMutex;
|
|
}
|
|
|
|
osl::Condition & getInitCondition()
|
|
{
|
|
static osl::Condition aCondition;
|
|
return aCondition;
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
static void ToolkitWorkerFunction( void* pArgs )
|
|
{
|
|
osl_setThreadName("VCLXToolkit VCL main thread");
|
|
|
|
css::uno::Reference<css::lang::XMultiServiceFactory> xServiceManager;
|
|
try
|
|
{
|
|
xServiceManager = ::comphelper::getProcessServiceFactory();
|
|
}
|
|
catch (const css::uno::DeploymentException&)
|
|
{
|
|
}
|
|
if (!xServiceManager.is())
|
|
{
|
|
css::uno::Reference<css::uno::XComponentContext> xContext =
|
|
::cppu::defaultBootstrap_InitialComponentContext();
|
|
|
|
xServiceManager.set( xContext->getServiceManager(), css::uno::UNO_QUERY_THROW );
|
|
// set global process service factory used by unotools config helpers
|
|
::comphelper::setProcessServiceFactory( xServiceManager );
|
|
}
|
|
|
|
VCLXToolkit * pTk = static_cast<VCLXToolkit *>(pArgs);
|
|
bInitedByVCLToolkit = !IsVCLInit() && InitVCL();
|
|
if( bInitedByVCLToolkit )
|
|
{
|
|
UnoWrapper* pUnoWrapper = new UnoWrapper( pTk );
|
|
UnoWrapperBase::SetUnoWrapper( pUnoWrapper );
|
|
}
|
|
getInitCondition().set();
|
|
if( bInitedByVCLToolkit )
|
|
{
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
Application::Execute();
|
|
}
|
|
try
|
|
{
|
|
pTk->dispose();
|
|
}
|
|
catch( css::uno::Exception & )
|
|
{
|
|
}
|
|
DeInitVCL();
|
|
}
|
|
else
|
|
{
|
|
// having the thread join itself is pretty stupid.
|
|
// but we can't get the osl_Thread to destroy here so just leak it.
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
// constructor, which might initialize VCL
|
|
VCLXToolkit::VCLXToolkit():
|
|
cppu::WeakComponentImplHelper<
|
|
css::awt::XToolkitExperimental,
|
|
css::awt::XToolkitRobot,
|
|
css::lang::XServiceInfo>( GetMutex() ),
|
|
m_aTopWindowListeners(rBHelper.rMutex),
|
|
m_aKeyHandlers(rBHelper.rMutex),
|
|
m_aFocusListeners(rBHelper.rMutex),
|
|
m_aEventListenerLink(LINK(this, VCLXToolkit, eventListenerHandler)),
|
|
m_aKeyListenerLink(LINK(this, VCLXToolkit, keyListenerHandler)),
|
|
m_bEventListener(false),
|
|
m_bKeyListener(false)
|
|
{
|
|
#ifndef IOS
|
|
osl::Guard< osl::Mutex > aGuard( getInitMutex() );
|
|
nVCLToolkitInstanceCount++;
|
|
if( ( nVCLToolkitInstanceCount == 1 ) && ( !Application::IsInMain() ) )
|
|
{
|
|
// setup execute thread
|
|
CreateMainLoopThread( ToolkitWorkerFunction, this );
|
|
getInitCondition().wait();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void SAL_CALL VCLXToolkit::disposing()
|
|
{
|
|
#ifndef IOS
|
|
{
|
|
osl::Guard< osl::Mutex > aGuard( getInitMutex() );
|
|
if( --nVCLToolkitInstanceCount == 0 )
|
|
{
|
|
if( bInitedByVCLToolkit )
|
|
{
|
|
Application::Quit();
|
|
JoinMainLoopThread();
|
|
bInitedByVCLToolkit = false;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
if (m_bEventListener)
|
|
{
|
|
::Application::RemoveEventListener(m_aEventListenerLink);
|
|
m_bEventListener = false;
|
|
}
|
|
if (m_bKeyListener)
|
|
{
|
|
::Application::RemoveKeyListener(m_aKeyListenerLink);
|
|
m_bKeyListener = false;
|
|
}
|
|
css::lang::EventObject aEvent(
|
|
getXWeak());
|
|
m_aTopWindowListeners.disposeAndClear(aEvent);
|
|
m_aKeyHandlers.disposeAndClear(aEvent);
|
|
m_aFocusListeners.disposeAndClear(aEvent);
|
|
}
|
|
|
|
|
|
css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::getDesktopWindow( )
|
|
{
|
|
css::uno::Reference< css::awt::XWindowPeer > xRef;
|
|
// 07/00: AppWindow doesn't exist anymore...
|
|
return xRef;
|
|
}
|
|
|
|
css::awt::Rectangle VCLXToolkit::getWorkArea( )
|
|
{
|
|
sal_Int32 nDisplay = Application::GetDisplayBuiltInScreen();
|
|
AbsoluteScreenPixelRectangle aWorkRect = Application::GetScreenPosSizePixel( nDisplay );
|
|
css::awt::Rectangle aNotherRect;
|
|
aNotherRect.X = aWorkRect.Left();
|
|
aNotherRect.Y = aWorkRect.Top();
|
|
aNotherRect.Width = aWorkRect.getOpenWidth();
|
|
aNotherRect.Height = aWorkRect.getOpenHeight();
|
|
return aNotherRect;
|
|
}
|
|
|
|
css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::createWindow( const css::awt::WindowDescriptor& rDescriptor )
|
|
{
|
|
return ImplCreateWindow( rDescriptor, MessBoxStyle::NONE );
|
|
}
|
|
|
|
css::uno::Reference< css::awt::XDevice > VCLXToolkit::createScreenCompatibleDevice( sal_Int32 Width, sal_Int32 Height )
|
|
{
|
|
::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
|
|
|
|
rtl::Reference<VCLXVirtualDevice> pVDev = new VCLXVirtualDevice;
|
|
|
|
SolarMutexGuard aSolarGuard;
|
|
|
|
VclPtrInstance<VirtualDevice> pV;
|
|
pV->SetOutputSizePixel( Size( Width, Height ) );
|
|
pVDev->SetVirtualDevice( pV );
|
|
|
|
return pVDev;
|
|
}
|
|
|
|
css::uno::Reference< css::awt::XRegion > VCLXToolkit::createRegion( )
|
|
{
|
|
::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
|
|
|
|
css::uno::Reference< css::awt::XRegion > xRef = new VCLXRegion;
|
|
return xRef;
|
|
}
|
|
|
|
class InfoBox : public MessBox
|
|
{
|
|
public:
|
|
InfoBox(vcl::Window* pParent, const OUString& rMessage)
|
|
: MessBox(pParent, MessBoxStyle::Ok | MessBoxStyle::DefaultOk, 0, OUString(), rMessage)
|
|
{
|
|
// Default Text is the display title from the application
|
|
if (GetText().isEmpty())
|
|
SetText(GetStandardInfoBoxText());
|
|
SetImage(GetStandardInfoBoxImage());
|
|
}
|
|
};
|
|
|
|
class ErrorBox : public MessBox
|
|
{
|
|
public:
|
|
ErrorBox(vcl::Window* pParent, MessBoxStyle nStyle, WinBits nWinBits, const OUString& rMessage)
|
|
: MessBox(pParent, nStyle, nWinBits, OUString(), rMessage)
|
|
{
|
|
// Default Text is the display title from the application
|
|
if (GetText().isEmpty())
|
|
SetText(GetStandardErrorBoxText());
|
|
SetImage(GetStandardErrorBoxImage());
|
|
}
|
|
};
|
|
|
|
class QueryBox : public MessBox
|
|
{
|
|
public:
|
|
QueryBox(vcl::Window* pParent, MessBoxStyle nStyle, WinBits nWinBits, const OUString& rMessage)
|
|
: MessBox(pParent, nStyle, nWinBits, OUString(), rMessage)
|
|
{
|
|
// Default Text is the display title from the application
|
|
if (GetText().isEmpty())
|
|
SetText(GetStandardQueryBoxText());
|
|
SetImage(GetStandardQueryBoxImage());
|
|
}
|
|
};
|
|
|
|
class WarningBox : public MessBox
|
|
{
|
|
public:
|
|
WarningBox(vcl::Window* pParent, MessBoxStyle nStyle, WinBits nWinBits, const OUString& rMessage)
|
|
: MessBox(pParent, nStyle, nWinBits, OUString(), rMessage)
|
|
{
|
|
// Default Text is the display title from the application
|
|
if (GetText().isEmpty())
|
|
SetText(GetStandardWarningBoxText());
|
|
SetImage(GetStandardWarningBoxImage());
|
|
}
|
|
};
|
|
|
|
|
|
struct RMItemData
|
|
{
|
|
bool b_Enabled;
|
|
sal_Int32 n_ID;
|
|
OUString Label;
|
|
};
|
|
|
|
typedef ::cppu::ImplInheritanceHelper < VCLXGraphicControl
|
|
, css::container::XContainerListener
|
|
, css::beans::XPropertyChangeListener
|
|
, css::awt::XItemEventBroadcaster
|
|
> SVTXRoadmap_Base;
|
|
class SVTXRoadmap final : public SVTXRoadmap_Base
|
|
{
|
|
public:
|
|
SVTXRoadmap();
|
|
|
|
void SAL_CALL disposing( const css::lang::EventObject& Source ) override { VCLXWindow::disposing( Source ); }
|
|
|
|
// css::awt::XVclWindowPeer
|
|
void SAL_CALL setProperty( const OUString& PropertyName, const css::uno::Any& Value ) override;
|
|
|
|
css::uno::Any SAL_CALL getProperty( const OUString& PropertyName ) override;
|
|
|
|
// XContainerListener
|
|
void SAL_CALL elementInserted( const css::container::ContainerEvent& rEvent ) override;
|
|
void SAL_CALL elementRemoved( const css::container::ContainerEvent& rEvent ) override;
|
|
void SAL_CALL elementReplaced( const css::container::ContainerEvent& rEvent ) override;
|
|
|
|
// XItemEventBroadcaster
|
|
virtual void SAL_CALL addItemListener( const css::uno::Reference< css::awt::XItemListener >& l ) override;
|
|
virtual void SAL_CALL removeItemListener( const css::uno::Reference< css::awt::XItemListener >& l ) override;
|
|
|
|
// XPropertyChangeListener
|
|
virtual void SAL_CALL propertyChange( const css::beans::PropertyChangeEvent& evt ) override;
|
|
|
|
private:
|
|
|
|
// VCLXGraphicControl overridables
|
|
virtual void ImplSetNewImage() override;
|
|
|
|
static void ImplGetPropertyIds( std::vector< sal_uInt16 > &aIds );
|
|
virtual void GetPropertyIds( std::vector< sal_uInt16 > &aIds ) override { return ImplGetPropertyIds( aIds ); }
|
|
|
|
static RMItemData GetRMItemData( const css::container::ContainerEvent& _rEvent );
|
|
|
|
virtual void ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) override;
|
|
|
|
virtual ~SVTXRoadmap() override;
|
|
|
|
ItemListenerMultiplexer maItemListeners;
|
|
};
|
|
|
|
|
|
|
|
|
|
SVTXRoadmap::SVTXRoadmap() : maItemListeners( *this )
|
|
{
|
|
}
|
|
|
|
SVTXRoadmap::~SVTXRoadmap()
|
|
{
|
|
}
|
|
|
|
void SVTXRoadmap::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
|
|
{
|
|
switch ( rVclWindowEvent.GetId() )
|
|
{
|
|
case VclEventId::RoadmapItemSelected:
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
|
|
if ( pField )
|
|
{
|
|
sal_Int16 CurItemID = pField->GetCurrentRoadmapItemID();
|
|
css::awt::ItemEvent aEvent;
|
|
aEvent.Selected = CurItemID;
|
|
aEvent.Highlighted = CurItemID;
|
|
aEvent.ItemId = CurItemID;
|
|
maItemListeners.itemStateChanged( aEvent );
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
SVTXRoadmap_Base::ProcessWindowEvent( rVclWindowEvent );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SVTXRoadmap::propertyChange( const css::beans::PropertyChangeEvent& evt )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
|
|
if ( !pField )
|
|
return;
|
|
|
|
css::uno::Reference< css::uno::XInterface > xRoadmapItem = evt.Source;
|
|
sal_Int32 nID = 0;
|
|
css::uno::Reference< css::beans::XPropertySet > xPropertySet( xRoadmapItem, css::uno::UNO_QUERY );
|
|
css::uno::Any aValue = xPropertySet->getPropertyValue("ID");
|
|
aValue >>= nID;
|
|
|
|
OUString sPropertyName = evt.PropertyName;
|
|
if ( sPropertyName == "Enabled" )
|
|
{
|
|
bool bEnable = false;
|
|
evt.NewValue >>= bEnable;
|
|
pField->EnableRoadmapItem( static_cast<vcl::RoadmapTypes::ItemId>(nID) , bEnable );
|
|
}
|
|
else if ( sPropertyName == "Label" )
|
|
{
|
|
OUString sLabel;
|
|
evt.NewValue >>= sLabel;
|
|
pField->ChangeRoadmapItemLabel( static_cast<vcl::RoadmapTypes::ItemId>(nID) , sLabel );
|
|
}
|
|
else if ( sPropertyName == "ID" )
|
|
{
|
|
sal_Int32 nNewID = 0;
|
|
evt.NewValue >>= nNewID;
|
|
evt.OldValue >>= nID;
|
|
pField->ChangeRoadmapItemID( static_cast<vcl::RoadmapTypes::ItemId>(nID), static_cast<vcl::RoadmapTypes::ItemId>(nNewID) );
|
|
}
|
|
// else
|
|
// TODO handle Interactive appropriately
|
|
}
|
|
|
|
void SVTXRoadmap::addItemListener( const css::uno::Reference< css::awt::XItemListener >& l )
|
|
{
|
|
maItemListeners.addInterface( l );
|
|
}
|
|
|
|
void SVTXRoadmap::removeItemListener( const css::uno::Reference< css::awt::XItemListener >& l )
|
|
{
|
|
maItemListeners.removeInterface( l );
|
|
}
|
|
|
|
RMItemData SVTXRoadmap::GetRMItemData( const css::container::ContainerEvent& _rEvent )
|
|
{
|
|
RMItemData aCurRMItemData;
|
|
css::uno::Reference< css::uno::XInterface > xRoadmapItem;
|
|
_rEvent.Element >>= xRoadmapItem;
|
|
css::uno::Reference< css::beans::XPropertySet > xPropertySet( xRoadmapItem, css::uno::UNO_QUERY );
|
|
if ( xPropertySet.is() )
|
|
{
|
|
css::uno::Any aValue = xPropertySet->getPropertyValue("Label");
|
|
aValue >>= aCurRMItemData.Label;
|
|
aValue = xPropertySet->getPropertyValue("ID");
|
|
aValue >>= aCurRMItemData.n_ID;
|
|
aValue = xPropertySet->getPropertyValue("Enabled");
|
|
aValue >>= aCurRMItemData.b_Enabled;
|
|
}
|
|
else
|
|
{
|
|
aCurRMItemData.b_Enabled = false;
|
|
aCurRMItemData.n_ID = 0;
|
|
}
|
|
return aCurRMItemData;
|
|
}
|
|
|
|
void SVTXRoadmap::elementInserted( const css::container::ContainerEvent& _rEvent )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
|
|
if ( pField )
|
|
{
|
|
RMItemData CurItemData = GetRMItemData( _rEvent );
|
|
sal_Int32 InsertIndex = 0;
|
|
_rEvent.Accessor >>= InsertIndex;
|
|
pField->InsertRoadmapItem( InsertIndex, CurItemData.Label, static_cast<vcl::RoadmapTypes::ItemId>(CurItemData.n_ID), CurItemData.b_Enabled );
|
|
}
|
|
}
|
|
|
|
void SVTXRoadmap::elementRemoved( const css::container::ContainerEvent& _rEvent )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
|
|
if ( pField )
|
|
{
|
|
sal_Int32 DelIndex = 0;
|
|
_rEvent.Accessor >>= DelIndex;
|
|
pField->DeleteRoadmapItem(DelIndex);
|
|
}
|
|
}
|
|
|
|
void SVTXRoadmap::elementReplaced( const css::container::ContainerEvent& _rEvent )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
|
|
if ( pField )
|
|
{
|
|
RMItemData CurItemData = GetRMItemData( _rEvent );
|
|
sal_Int32 ReplaceIndex = 0;
|
|
_rEvent.Accessor >>= ReplaceIndex;
|
|
pField->ReplaceRoadmapItem( ReplaceIndex, CurItemData.Label, static_cast<vcl::RoadmapTypes::ItemId>(CurItemData.n_ID), CurItemData.b_Enabled );
|
|
}
|
|
}
|
|
|
|
void SVTXRoadmap::setProperty( const OUString& PropertyName, const css::uno::Any& Value)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
|
|
if ( pField )
|
|
{
|
|
sal_uInt16 nPropType = GetPropertyId( PropertyName );
|
|
switch (nPropType)
|
|
{
|
|
case BASEPROPERTY_COMPLETE:
|
|
{
|
|
bool b = false;
|
|
Value >>= b;
|
|
pField->SetRoadmapComplete( b);
|
|
}
|
|
break;
|
|
|
|
case BASEPROPERTY_ACTIVATED:
|
|
{
|
|
bool b = false;
|
|
Value >>= b;
|
|
pField->SetRoadmapInteractive( b);
|
|
}
|
|
break;
|
|
|
|
case BASEPROPERTY_CURRENTITEMID:
|
|
{
|
|
sal_Int32 nId = 0;
|
|
Value >>= nId;
|
|
pField->SelectRoadmapItemByID( static_cast<vcl::RoadmapTypes::ItemId>(nId) );
|
|
}
|
|
break;
|
|
|
|
case BASEPROPERTY_TEXT:
|
|
{
|
|
OUString aStr;
|
|
Value >>= aStr;
|
|
pField->SetText( aStr );
|
|
pField->Invalidate();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
SVTXRoadmap_Base::setProperty( PropertyName, Value );
|
|
break;
|
|
}
|
|
|
|
}
|
|
else
|
|
SVTXRoadmap_Base::setProperty( PropertyName, Value );
|
|
}
|
|
|
|
|
|
css::uno::Any SVTXRoadmap::getProperty( const OUString& PropertyName )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
|
|
css::uno::Any aReturn;
|
|
|
|
VclPtr<::vcl::ORoadmap> pField = GetAs< vcl::ORoadmap >();
|
|
if ( pField )
|
|
{
|
|
sal_uInt16 nPropType = GetPropertyId( PropertyName );
|
|
switch (nPropType)
|
|
{
|
|
case BASEPROPERTY_COMPLETE:
|
|
aReturn <<= pField->IsRoadmapComplete();
|
|
break;
|
|
case BASEPROPERTY_ACTIVATED:
|
|
aReturn <<= pField->IsRoadmapInteractive();
|
|
break;
|
|
case BASEPROPERTY_CURRENTITEMID:
|
|
aReturn <<= pField->GetCurrentRoadmapItemID();
|
|
break;
|
|
default:
|
|
aReturn = SVTXRoadmap_Base::getProperty(PropertyName);
|
|
break;
|
|
}
|
|
}
|
|
return aReturn;
|
|
}
|
|
|
|
void SVTXRoadmap::ImplSetNewImage()
|
|
{
|
|
OSL_PRECOND( GetWindow(), "SVTXRoadmap::ImplSetNewImage: window is required to be not-NULL!" );
|
|
VclPtr< ::vcl::ORoadmap > pButton = GetAs< ::vcl::ORoadmap >();
|
|
pButton->SetRoadmapBitmap( GetImage().GetBitmapEx() );
|
|
}
|
|
|
|
void SVTXRoadmap::ImplGetPropertyIds( std::vector< sal_uInt16 > &rIds )
|
|
{
|
|
PushPropertyIds( rIds,
|
|
BASEPROPERTY_COMPLETE,
|
|
BASEPROPERTY_ACTIVATED,
|
|
BASEPROPERTY_CURRENTITEMID,
|
|
BASEPROPERTY_TEXT,
|
|
0);
|
|
VCLXWindow::ImplGetPropertyIds( rIds, true );
|
|
VCLXGraphicControl::ImplGetPropertyIds( rIds );
|
|
}
|
|
|
|
vcl::Window* VCLXToolkit::ImplCreateWindow( rtl::Reference<VCLXWindow>* ppNewComp,
|
|
const css::awt::WindowDescriptor& rDescriptor,
|
|
vcl::Window* pParent, WinBits nWinBits, MessBoxStyle nMessBoxStyle )
|
|
{
|
|
OUString aServiceName = rDescriptor.WindowServiceName.toAsciiLowerCase();
|
|
|
|
VclPtr<vcl::Window> pNewWindow;
|
|
WindowType nType = ImplGetComponentType( aServiceName );
|
|
bool bFrameControl = false;
|
|
if ( aServiceName == "frame" )
|
|
bFrameControl = true;
|
|
if ( aServiceName == "tabcontrolnotabs" )
|
|
{
|
|
nWinBits |= WB_NOBORDER;
|
|
nType = ImplGetComponentType( "tabcontrol" );
|
|
}
|
|
if ( !pParent )
|
|
{
|
|
// If the component needs a parent, then return NULL,
|
|
// some time later css::uno::Exception...
|
|
bool bException = true;
|
|
if ( ( nType == WindowType::DIALOG )
|
|
|| ( nType == WindowType::MODELESSDIALOG )
|
|
|| ( nType == WindowType::MESSBOX )
|
|
|| ( nType == WindowType::INFOBOX )
|
|
|| ( nType == WindowType::WARNINGBOX )
|
|
|| ( nType == WindowType::ERRORBOX )
|
|
|| ( nType == WindowType::QUERYBOX )
|
|
)
|
|
bException = false;
|
|
else if ( ( nType == WindowType::WINDOW ) ||
|
|
( nType == WindowType::WORKWINDOW ) ||
|
|
( nType == WindowType::TOOLKIT_FRAMEWINDOW ) )
|
|
{
|
|
if ( rDescriptor.Type == css::awt::WindowClass_TOP )
|
|
bException = false;
|
|
}
|
|
|
|
if ( bException )
|
|
{
|
|
*ppNewComp = nullptr;
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
if ( nType != WindowType::NONE )
|
|
{
|
|
SolarMutexGuard aVclGuard;
|
|
switch ( nType )
|
|
{
|
|
case WindowType::CANCELBUTTON:
|
|
pNewWindow = VclPtr<CancelButton>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXButton;
|
|
break;
|
|
case WindowType::CHECKBOX:
|
|
pNewWindow = VclPtr<CheckBox>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXCheckBox;
|
|
break;
|
|
case WindowType::COMBOBOX:
|
|
pNewWindow = VclPtr<ComboBox>::Create( pParent, nWinBits|WB_AUTOHSCROLL );
|
|
static_cast<ComboBox*>(pNewWindow.get())->EnableAutoSize( false );
|
|
*ppNewComp = new VCLXComboBox;
|
|
break;
|
|
case WindowType::CURRENCYBOX:
|
|
pNewWindow = VclPtr<CurrencyBox>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::CURRENCYFIELD:
|
|
pNewWindow = VclPtr<CurrencyField>::Create( pParent, nWinBits );
|
|
static_cast<CurrencyField*>(pNewWindow.get())->EnableEmptyFieldValue( true );
|
|
*ppNewComp = new VCLXNumericField;
|
|
static_cast<VCLXFormattedSpinField*>((*ppNewComp).get())->SetFormatter( static_cast<FormatterBase*>(static_cast<CurrencyField*>(pNewWindow.get())) );
|
|
break;
|
|
case WindowType::DATEBOX:
|
|
pNewWindow = VclPtr<DateBox>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::DOCKINGAREA:
|
|
pNewWindow = VclPtr<DockingAreaWindow>::Create( pParent );
|
|
break;
|
|
case WindowType::MULTILINEEDIT:
|
|
pNewWindow = VclPtr<MultiLineEdit>::Create(pParent, nWinBits|WB_IGNORETAB);
|
|
static_cast<MultiLineEdit*>(pNewWindow.get())->DisableSelectionOnFocus();
|
|
*ppNewComp = new VCLXMultiLineEdit;
|
|
break;
|
|
case WindowType::EDIT:
|
|
pNewWindow = VclPtr<Edit>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXEdit;
|
|
break;
|
|
case WindowType::ERRORBOX:
|
|
pNewWindow = VclPtr<ErrorBox>::Create( pParent, nMessBoxStyle, nWinBits, OUString() );
|
|
*ppNewComp = new VCLXMessageBox;
|
|
break;
|
|
case WindowType::FIXEDBITMAP:
|
|
pNewWindow = VclPtr<FixedBitmap>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::FIXEDIMAGE:
|
|
pNewWindow = VclPtr<ImageControl>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXImageControl;
|
|
break;
|
|
case WindowType::FIXEDLINE:
|
|
pNewWindow = VclPtr<FixedLine>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::FIXEDTEXT:
|
|
pNewWindow = VclPtr<FixedText>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXFixedText;
|
|
break;
|
|
case WindowType::FLOATINGWINDOW:
|
|
pNewWindow = VclPtr<FloatingWindow>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::GROUPBOX:
|
|
pNewWindow = VclPtr<GroupBox>::Create( pParent, nWinBits );
|
|
if ( bFrameControl )
|
|
{
|
|
GroupBox* pGroupBox = static_cast< GroupBox* >( pNewWindow.get() );
|
|
*ppNewComp = new VCLXFrame;
|
|
// Frame control needs to receive
|
|
// Mouse events
|
|
pGroupBox->SetMouseTransparent( false );
|
|
}
|
|
break;
|
|
case WindowType::HELPBUTTON:
|
|
pNewWindow = VclPtr<HelpButton>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXButton;
|
|
break;
|
|
case WindowType::IMAGEBUTTON:
|
|
pNewWindow = VclPtr<ImageButton>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXButton;
|
|
break;
|
|
case WindowType::INFOBOX:
|
|
pNewWindow = VclPtr<InfoBox>::Create( pParent, OUString() );
|
|
*ppNewComp = new VCLXMessageBox;
|
|
break;
|
|
case WindowType::LISTBOX:
|
|
pNewWindow = VclPtr<ListBox>::Create( pParent, nWinBits|WB_SIMPLEMODE|WB_AUTOHSCROLL );
|
|
static_cast<ListBox*>(pNewWindow.get())->EnableAutoSize( false );
|
|
*ppNewComp = new VCLXListBox;
|
|
break;
|
|
case WindowType::LONGCURRENCYBOX:
|
|
pNewWindow = VclPtr<LongCurrencyBox>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::MENUBUTTON:
|
|
pNewWindow = VclPtr<MenuButton>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXButton;
|
|
break;
|
|
case WindowType::MESSBOX:
|
|
pNewWindow = VclPtr<MessBox>::Create( pParent, nMessBoxStyle, nWinBits, OUString(), OUString() );
|
|
*ppNewComp = new VCLXMessageBox;
|
|
break;
|
|
case WindowType::METRICBOX:
|
|
pNewWindow = VclPtr<MetricBox>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::METRICFIELD:
|
|
pNewWindow = VclPtr<MetricField>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXMetricField;
|
|
static_cast<VCLXFormattedSpinField*>((*ppNewComp).get())->SetFormatter( static_cast<FormatterBase*>(static_cast<MetricField*>(pNewWindow.get())) );
|
|
break;
|
|
case WindowType::DIALOG:
|
|
case WindowType::MODELESSDIALOG:
|
|
{
|
|
// Modal/Modeless only via Show/Execute
|
|
if ( (pParent == nullptr ) && ( rDescriptor.ParentIndex == -1 ) )
|
|
pNewWindow = VclPtr<toolkit::ScrollableDialog>::Create( nullptr, nWinBits, Dialog::InitFlag::NoParent );
|
|
else
|
|
pNewWindow = VclPtr<toolkit::ScrollableDialog>::Create( pParent, nWinBits );
|
|
// #i70217# Don't always create a new component object. It's possible that VCL has called
|
|
// GetComponentInterface( sal_True ) in the Dialog ctor itself (see Window::IsTopWindow() )
|
|
// which creates a component object.
|
|
css::uno::Reference< css::awt::XWindowPeer > xWinPeer = pNewWindow->GetComponentInterface( false );
|
|
if ( xWinPeer.is() )
|
|
*ppNewComp = dynamic_cast< VCLXDialog* >( xWinPeer.get() );
|
|
else
|
|
*ppNewComp = new VCLXDialog;
|
|
}
|
|
break;
|
|
case WindowType::MOREBUTTON:
|
|
pNewWindow = VclPtr<MoreButton>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXButton;
|
|
break;
|
|
case WindowType::MULTILISTBOX:
|
|
pNewWindow = VclPtr<MultiListBox>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXListBox;
|
|
break;
|
|
case WindowType::NUMERICBOX:
|
|
pNewWindow = VclPtr<NumericBox>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::OKBUTTON:
|
|
pNewWindow = VclPtr<OKButton>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXButton;
|
|
break;
|
|
case WindowType::PATTERNBOX:
|
|
pNewWindow = VclPtr<PatternBox>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::PATTERNFIELD:
|
|
pNewWindow = VclPtr<PatternField>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXPatternField;
|
|
static_cast<VCLXFormattedSpinField*>((*ppNewComp).get())->SetFormatter( static_cast<FormatterBase*>(static_cast<PatternField*>(pNewWindow.get())) );
|
|
break;
|
|
case WindowType::PUSHBUTTON:
|
|
pNewWindow = VclPtr<PushButton>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXButton;
|
|
break;
|
|
case WindowType::QUERYBOX:
|
|
pNewWindow = VclPtr<QueryBox>::Create( pParent, nMessBoxStyle, nWinBits, OUString() );
|
|
*ppNewComp = new VCLXMessageBox;
|
|
break;
|
|
case WindowType::RADIOBUTTON:
|
|
pNewWindow = VclPtr<RadioButton>::Create(pParent, false, nWinBits);
|
|
*ppNewComp = new VCLXRadioButton;
|
|
|
|
// by default, disable RadioCheck
|
|
// Since the VCLXRadioButton really cares for its RadioCheck settings, this is important:
|
|
// if we enable it, the VCLXRadioButton will use RadioButton::Check instead of RadioButton::SetState
|
|
// This leads to a strange behaviour if the control is newly created: when settings the initial
|
|
// state to "checked", the RadioButton::Check (called because RadioCheck=sal_True) will uncheck
|
|
// _all_other_ radio buttons in the same group. However, at this moment the grouping of the controls
|
|
// is not really valid: the controls are grouped after they have been created, but we're still in
|
|
// the creation process, so the RadioButton::Check relies on invalid grouping information.
|
|
// 07.08.2001 - #87254# - frank.schoenheit@sun.com
|
|
static_cast<RadioButton*>(pNewWindow.get())->EnableRadioCheck( false );
|
|
break;
|
|
case WindowType::SCROLLBAR:
|
|
pNewWindow = VclPtr<ScrollBar>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXScrollBar;
|
|
break;
|
|
case WindowType::SCROLLBARBOX:
|
|
pNewWindow = VclPtr<ScrollBarBox>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::SPINBUTTON:
|
|
pNewWindow = VclPtr<SpinButton>::Create( pParent, nWinBits );
|
|
*ppNewComp = new ::toolkit::VCLXSpinButton;
|
|
break;
|
|
case WindowType::SPINFIELD:
|
|
pNewWindow = VclPtr<SpinField>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXNumericField;
|
|
break;
|
|
case WindowType::SPLITTER:
|
|
pNewWindow = VclPtr<Splitter>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::SPLITWINDOW:
|
|
pNewWindow = VclPtr<SplitWindow>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::STATUSBAR:
|
|
pNewWindow = VclPtr<StatusBar>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::TOOLKIT_SYSTEMCHILDWINDOW:
|
|
pNewWindow = VclPtr<SystemChildWindow>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXSystemDependentWindow();
|
|
break;
|
|
case WindowType::TABCONTROL:
|
|
pNewWindow = VclPtr<TabControl>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXMultiPage;
|
|
break;
|
|
case WindowType::TABDIALOG:
|
|
pNewWindow = VclPtr<TabDialog>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::TABPAGE:
|
|
{
|
|
pNewWindow = VclPtr<TabPage>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXTabPage;
|
|
}
|
|
break;
|
|
case WindowType::TIMEBOX:
|
|
pNewWindow = VclPtr<TimeBox>::Create( pParent, nWinBits );
|
|
break;
|
|
case WindowType::TIMEFIELD:
|
|
pNewWindow = VclPtr<TimeField>::Create( pParent, nWinBits );
|
|
static_cast<TimeField*>(pNewWindow.get())->EnableEmptyFieldValue( true );
|
|
*ppNewComp = new VCLXTimeField;
|
|
static_cast<VCLXFormattedSpinField*>((*ppNewComp).get())->SetFormatter( static_cast<FormatterBase*>(static_cast<TimeField*>(pNewWindow.get())) );
|
|
break;
|
|
case WindowType::TOOLBOX:
|
|
pNewWindow = VclPtr<ToolBox>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXToolBox;
|
|
break;
|
|
case WindowType::TRISTATEBOX:
|
|
pNewWindow = VclPtr<CheckBox>::Create( pParent, nWinBits );
|
|
static_cast<CheckBox*>(pNewWindow.get())->EnableTriState(true);
|
|
break;
|
|
case WindowType::WARNINGBOX:
|
|
pNewWindow = VclPtr<WarningBox>::Create( pParent, nMessBoxStyle, nWinBits, OUString() );
|
|
*ppNewComp = new VCLXMessageBox;
|
|
break;
|
|
case WindowType::WORKWINDOW:
|
|
case WindowType::WINDOW:
|
|
case WindowType::TOOLKIT_FRAMEWINDOW:
|
|
case WindowType::DOCKINGWINDOW:
|
|
if ( rDescriptor.Type == css::awt::WindowClass_TOP )
|
|
{
|
|
if (nType == WindowType::DOCKINGWINDOW )
|
|
pNewWindow = VclPtr<DockingWindow>::Create( pParent, nWinBits );
|
|
else
|
|
{
|
|
if ((pParent == nullptr) && rDescriptor.Parent.is())
|
|
{
|
|
// try to get a system dependent window handle
|
|
css::uno::Reference< css::awt::XSystemDependentWindowPeer > xSystemDepParent(rDescriptor.Parent, css::uno::UNO_QUERY);
|
|
|
|
if (xSystemDepParent.is())
|
|
{
|
|
sal_Int8 processID[16];
|
|
|
|
rtl_getGlobalProcessId( reinterpret_cast<sal_uInt8*>(processID) );
|
|
|
|
// coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
|
|
css::uno::Sequence<sal_Int8> processIdSeq(processID, 16);
|
|
|
|
css::uno::Any anyHandle = xSystemDepParent->getWindowHandle(processIdSeq, SYSTEM_DEPENDENT_TYPE);
|
|
|
|
// use sal_Int64 here to accommodate all int types
|
|
// uno::Any shift operator will upcast if necessary
|
|
sal_Int64 nWindowHandle = 0;
|
|
bool bXEmbed = false;
|
|
|
|
bool bUseParentData = true;
|
|
if( ! (anyHandle >>= nWindowHandle) )
|
|
{
|
|
css::uno::Sequence< css::beans::NamedValue > aProps;
|
|
if( anyHandle >>= aProps )
|
|
{
|
|
for( const css::beans::NamedValue& rProp : std::as_const(aProps) )
|
|
{
|
|
if ( rProp.Name == "WINDOW" )
|
|
rProp.Value >>= nWindowHandle;
|
|
else if ( rProp.Name == "XEMBED" )
|
|
rProp.Value >>= bXEmbed;
|
|
}
|
|
}
|
|
else
|
|
bUseParentData = false;
|
|
}
|
|
|
|
if( bUseParentData )
|
|
{
|
|
SystemParentData aParentData;
|
|
aParentData.nSize = sizeof( aParentData );
|
|
#if defined MACOSX
|
|
aParentData.pView = reinterpret_cast<NSView*>(nWindowHandle);
|
|
#elif defined ANDROID
|
|
// Nothing
|
|
#elif defined IOS
|
|
// Nothing
|
|
#elif defined UNX
|
|
aParentData.aWindow = nWindowHandle;
|
|
aParentData.bXEmbedSupport = bXEmbed;
|
|
#elif defined _WIN32
|
|
aParentData.hWnd = reinterpret_cast<HWND>(nWindowHandle);
|
|
#endif
|
|
pNewWindow = VclPtr<WorkWindow>::Create( &aParentData );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!pNewWindow)
|
|
pNewWindow = VclPtr<WorkWindow>::Create( pParent, nWinBits );
|
|
}
|
|
|
|
*ppNewComp = new VCLXTopWindow();
|
|
}
|
|
else if ( rDescriptor.Type == css::awt::WindowClass_CONTAINER )
|
|
{
|
|
if (nType == WindowType::DOCKINGWINDOW )
|
|
pNewWindow = VclPtr<DockingWindow>::Create( pParent, nWinBits );
|
|
else
|
|
pNewWindow = VclPtr<vcl::Window>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXContainer;
|
|
}
|
|
else
|
|
{
|
|
if (nType == WindowType::DOCKINGWINDOW )
|
|
pNewWindow = VclPtr<DockingWindow>::Create( pParent, nWinBits );
|
|
else
|
|
pNewWindow = VclPtr<vcl::Window>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXWindow;
|
|
}
|
|
break;
|
|
case WindowType::CONTROL:
|
|
if ( aServiceName == "tabpagecontainer" )
|
|
{
|
|
// TabControl has a special case for tabs without border: they are displayed
|
|
// in a different way, so we need to ensure that this style is not set, so
|
|
// we can guarantee normal tab behavior
|
|
pNewWindow = VclPtr<TabControl>::Create( pParent, nWinBits & (~WB_NOBORDER));
|
|
*ppNewComp = new VCLXTabPageContainer;
|
|
}
|
|
else if ( aServiceName == "animatedimages" )
|
|
{
|
|
pNewWindow = VclPtr<Throbber>::Create( pParent, nWinBits );
|
|
*ppNewComp = new ::toolkit::AnimatedImagesPeer;
|
|
}
|
|
else if (aServiceName == "roadmap")
|
|
{
|
|
pNewWindow = VclPtr<::vcl::ORoadmap>::Create( pParent, WB_TABSTOP );
|
|
*ppNewComp = new SVTXRoadmap;
|
|
}
|
|
else if (aServiceName == "fixedhyperlink")
|
|
{
|
|
pNewWindow = VclPtr<FixedHyperlink>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXFixedHyperlink;
|
|
}
|
|
else if (aServiceName == "progressbar")
|
|
{
|
|
pNewWindow = VclPtr<ProgressBar>::Create( pParent, nWinBits, ProgressBar::BarStyle::Progress );
|
|
*ppNewComp = new VCLXProgressBar;
|
|
}
|
|
else if (aServiceName == "filecontrol")
|
|
{
|
|
pNewWindow = VclPtr<FileControl>::Create( pParent, nWinBits );
|
|
*ppNewComp = new VCLXFileControl;
|
|
}
|
|
else if (aServiceName == "tree")
|
|
{
|
|
rtl::Reference<TreeControlPeer> pPeer = new TreeControlPeer;
|
|
*ppNewComp = pPeer;
|
|
pNewWindow = pPeer->createVclControl( pParent, nWinBits );
|
|
}
|
|
else if (aServiceName == "formattedfield")
|
|
{
|
|
pNewWindow = VclPtr<FormattedField>::Create( pParent, nWinBits );
|
|
*ppNewComp = new SVTXFormattedField;
|
|
}
|
|
else if (aServiceName == "numericfield")
|
|
{
|
|
pNewWindow = VclPtr<DoubleNumericField>::Create( pParent, nWinBits );
|
|
*ppNewComp = new SVTXNumericField;
|
|
}
|
|
else if (aServiceName == "longcurrencyfield")
|
|
{
|
|
pNewWindow = VclPtr<DoubleCurrencyField>::Create( pParent, nWinBits );
|
|
*ppNewComp = new SVTXCurrencyField;
|
|
}
|
|
else if (aServiceName == "datefield")
|
|
{
|
|
pNewWindow = VclPtr<CalendarField>::Create(pParent, nWinBits);
|
|
static_cast<CalendarField*>(pNewWindow.get())->EnableToday();
|
|
static_cast<CalendarField*>(pNewWindow.get())->EnableNone();
|
|
static_cast<CalendarField*>(pNewWindow.get())->EnableEmptyFieldValue( true );
|
|
rtl::Reference<SVTXDateField> newComp = new SVTXDateField;
|
|
*ppNewComp = newComp;
|
|
newComp->SetFormatter( static_cast<FormatterBase*>(static_cast<DateField*>(pNewWindow.get())) );
|
|
}
|
|
else if (aServiceName == "grid")
|
|
{
|
|
pNewWindow = VclPtr<::svt::table::TableControl>::Create(pParent, nWinBits);
|
|
*ppNewComp = new SVTXGridControl;
|
|
}
|
|
break;
|
|
default:
|
|
OSL_ENSURE( false, "VCLXToolkit::ImplCreateWindow: unknown window type!" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// tdf#126717 default that formcontrols show accelerators
|
|
if (Control* pControl = dynamic_cast<Control*>(pNewWindow.get()))
|
|
pControl->SetShowAccelerator(true);
|
|
return pNewWindow;
|
|
}
|
|
|
|
css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::ImplCreateWindow(
|
|
const css::awt::WindowDescriptor& rDescriptor,
|
|
MessBoxStyle nForceMessBoxStyle )
|
|
{
|
|
::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
|
|
|
|
SolarMutexGuard aSolarGuard;
|
|
|
|
css::uno::Reference< css::awt::XVclWindowPeer > xRef;
|
|
|
|
VclPtr<vcl::Window> pParent;
|
|
if ( rDescriptor.Parent.is() )
|
|
{
|
|
VCLXWindow* pParentComponent = dynamic_cast<VCLXWindow*>( rDescriptor.Parent.get() );
|
|
|
|
// #103939# Don't throw assertion, may be it's a system dependent window, used in ImplCreateWindow.
|
|
// DBG_ASSERT( pParentComponent, "ParentComponent not valid" );
|
|
|
|
if ( pParentComponent )
|
|
pParent = pParentComponent->GetWindow();
|
|
}
|
|
std::pair<WinBits, MessBoxStyle> aPair = ImplGetWinBits( rDescriptor.WindowAttributes,
|
|
ImplGetComponentType( rDescriptor.WindowServiceName ) );
|
|
WinBits nWinBits = aPair.first;
|
|
aPair.second |= nForceMessBoxStyle;
|
|
|
|
rtl::Reference<VCLXWindow> pNewComp;
|
|
|
|
vcl::Window* pNewWindow = ImplCreateWindow( &pNewComp, rDescriptor, pParent, nWinBits, aPair.second );
|
|
|
|
DBG_ASSERT( pNewWindow, "createWindow: Unknown Component!" );
|
|
SAL_INFO_IF( !pNewComp, "toolkit", "createWindow: No special Interface!" );
|
|
|
|
if ( pNewWindow )
|
|
{
|
|
pNewWindow->SetCreatedWithToolkit( true );
|
|
//pNewWindow->SetPosPixel( Point() ); // do not force (0,0) position, keep default pos instead
|
|
|
|
if ( rDescriptor.WindowAttributes & css::awt::WindowAttribute::MINSIZE )
|
|
{
|
|
pNewWindow->SetSizePixel( Size() );
|
|
}
|
|
else if ( rDescriptor.WindowAttributes & css::awt::WindowAttribute::FULLSIZE )
|
|
{
|
|
if ( pParent )
|
|
pNewWindow->SetSizePixel( pParent->GetOutputSizePixel() );
|
|
}
|
|
else if ( !VCLUnoHelper::IsZero( rDescriptor.Bounds ) )
|
|
{
|
|
tools::Rectangle aRect = VCLRectangle( rDescriptor.Bounds );
|
|
pNewWindow->SetPosSizePixel( aRect.TopLeft(), aRect.GetSize() );
|
|
}
|
|
|
|
if ( !pNewComp )
|
|
{
|
|
// Default-Interface
|
|
xRef = pNewWindow->GetComponentInterface();
|
|
}
|
|
else
|
|
{
|
|
xRef = pNewComp;
|
|
pNewWindow->SetComponentInterface( xRef );
|
|
}
|
|
DBG_ASSERT( pNewWindow->GetComponentInterface( false ) == xRef,
|
|
"VCLXToolkit::createWindow: did #133706# resurge?" );
|
|
|
|
if ( rDescriptor.WindowAttributes & css::awt::WindowAttribute::SHOW )
|
|
pNewWindow->Show();
|
|
}
|
|
|
|
return xRef;
|
|
}
|
|
|
|
css::uno::Sequence< css::uno::Reference< css::awt::XWindowPeer > > VCLXToolkit::createWindows( const css::uno::Sequence< css::awt::WindowDescriptor >& rDescriptors )
|
|
{
|
|
::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
|
|
|
|
sal_uInt32 nComponents = rDescriptors.getLength();
|
|
css::uno::Sequence< css::uno::Reference< css::awt::XWindowPeer > > aSeq( nComponents );
|
|
for ( sal_uInt32 n = 0; n < nComponents; n++ )
|
|
{
|
|
css::awt::WindowDescriptor aDescr = rDescriptors.getConstArray()[n];
|
|
|
|
if ( aDescr.ParentIndex == -1 )
|
|
aDescr.Parent = nullptr;
|
|
else if ( ( aDescr.ParentIndex >= 0 ) && ( o3tl::make_unsigned(aDescr.ParentIndex) < n ) )
|
|
aDescr.Parent = aSeq.getConstArray()[aDescr.ParentIndex];
|
|
aSeq.getArray()[n] = createWindow( aDescr );
|
|
}
|
|
return aSeq;
|
|
}
|
|
|
|
// css::awt::XSystemChildFactory
|
|
css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::createSystemChild( const css::uno::Any& Parent, const css::uno::Sequence< sal_Int8 >& /*ProcessId*/, sal_Int16 nSystemType )
|
|
{
|
|
VclPtr<vcl::Window> pChildWindow;
|
|
if ( nSystemType == SYSTEM_DEPENDENT_TYPE )
|
|
{
|
|
// use sal_Int64 here to accommodate all int types
|
|
// uno::Any shift operator will upcast if necessary
|
|
sal_Int64 nWindowHandle = 0;
|
|
bool bXEmbed = false;
|
|
|
|
bool bUseParentData = true;
|
|
if( ! (Parent >>= nWindowHandle) )
|
|
{
|
|
css::uno::Sequence< css::beans::NamedValue > aProps;
|
|
if( Parent >>= aProps )
|
|
{
|
|
for( const css::beans::NamedValue& rProp : std::as_const(aProps) )
|
|
{
|
|
if ( rProp.Name == "WINDOW" )
|
|
rProp.Value >>= nWindowHandle;
|
|
else if ( rProp.Name == "XEMBED" )
|
|
rProp.Value >>= bXEmbed;
|
|
}
|
|
}
|
|
else
|
|
bUseParentData = false;
|
|
}
|
|
|
|
if( bUseParentData )
|
|
{
|
|
SystemParentData aParentData;
|
|
aParentData.nSize = sizeof( aParentData );
|
|
#if defined MACOSX
|
|
aParentData.pView = reinterpret_cast<NSView*>(nWindowHandle);
|
|
#elif defined ANDROID
|
|
// Nothing
|
|
#elif defined IOS
|
|
// Nothing
|
|
#elif defined UNX
|
|
aParentData.aWindow = nWindowHandle;
|
|
aParentData.bXEmbedSupport = bXEmbed;
|
|
#elif defined _WIN32
|
|
aParentData.hWnd = reinterpret_cast<HWND>(nWindowHandle);
|
|
#endif
|
|
SolarMutexGuard aGuard;
|
|
try
|
|
{
|
|
pChildWindow.reset( VclPtr<WorkWindow>::Create( &aParentData ) );
|
|
}
|
|
catch ( const css::uno::RuntimeException & )
|
|
{
|
|
// system child window could not be created
|
|
DBG_UNHANDLED_EXCEPTION("toolkit");
|
|
pChildWindow.clear();
|
|
}
|
|
}
|
|
}
|
|
else if (nSystemType == css::lang::SystemDependent::SYSTEM_JAVA)
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
pChildWindow.reset(VclPtr<WorkWindow>::Create(nullptr, Parent));
|
|
}
|
|
|
|
css::uno::Reference< css::awt::XVclWindowPeer > xPeer;
|
|
if ( pChildWindow )
|
|
{
|
|
rtl::Reference<VCLXTopWindow> pPeer = new VCLXTopWindow;
|
|
SolarMutexGuard aGuard;
|
|
pPeer->SetWindow( pChildWindow );
|
|
xPeer = pPeer;
|
|
pChildWindow->SetWindowPeer(xPeer, pPeer.get());
|
|
}
|
|
|
|
return xPeer;
|
|
}
|
|
|
|
// css::awt::XMessageBoxFactory
|
|
css::uno::Reference< css::awt::XMessageBox > SAL_CALL VCLXToolkit::createMessageBox(
|
|
const css::uno::Reference< css::awt::XWindowPeer >& aParent,
|
|
css::awt::MessageBoxType eType,
|
|
::sal_Int32 aButtons,
|
|
const OUString& aTitle,
|
|
const OUString& aMessage )
|
|
{
|
|
css::awt::WindowDescriptor aDescriptor;
|
|
|
|
sal_Int32 nWindowAttributes = css::awt::WindowAttribute::BORDER|css::awt::WindowAttribute::MOVEABLE|css::awt::WindowAttribute::CLOSEABLE;
|
|
|
|
// Map button definitions to window attributes
|
|
if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_OK )
|
|
nWindowAttributes |= css::awt::VclWindowPeerAttribute::OK;
|
|
else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_OK_CANCEL )
|
|
nWindowAttributes |= css::awt::VclWindowPeerAttribute::OK_CANCEL;
|
|
else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_YES_NO )
|
|
nWindowAttributes |= css::awt::VclWindowPeerAttribute::YES_NO;
|
|
else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_YES_NO_CANCEL )
|
|
nWindowAttributes |= css::awt::VclWindowPeerAttribute::YES_NO_CANCEL;
|
|
else if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_RETRY_CANCEL )
|
|
nWindowAttributes |= css::awt::VclWindowPeerAttribute::RETRY_CANCEL;
|
|
|
|
// Map default button definitions to window attributes
|
|
if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_OK )
|
|
nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_OK;
|
|
else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_CANCEL )
|
|
nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_CANCEL;
|
|
else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_YES )
|
|
nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_YES;
|
|
else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_NO )
|
|
nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_NO;
|
|
else if (sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_RETRY )
|
|
nWindowAttributes |= css::awt::VclWindowPeerAttribute::DEF_RETRY;
|
|
|
|
// No more bits for VclWindowPeerAttribute possible. Mapping must be
|
|
// done explicitly using VCL methods
|
|
MessBoxStyle nAddWinBits = MessBoxStyle::NONE;
|
|
if (( aButtons & 0x0000ffffL ) == css::awt::MessageBoxButtons::BUTTONS_ABORT_IGNORE_RETRY )
|
|
nAddWinBits |= MessBoxStyle::AbortRetryIgnore;
|
|
if ( sal_Int32( aButtons & 0xffff0000L ) == css::awt::MessageBoxButtons::DEFAULT_BUTTON_IGNORE )
|
|
nAddWinBits |= MessBoxStyle::DefaultIgnore;
|
|
|
|
OUString aType;
|
|
lcl_convertMessageBoxType( aType, eType );
|
|
|
|
aDescriptor.Type = css::awt::WindowClass_MODALTOP;
|
|
aDescriptor.WindowServiceName = aType;
|
|
aDescriptor.ParentIndex = -1;
|
|
aDescriptor.Parent = aParent;
|
|
aDescriptor.WindowAttributes = nWindowAttributes;
|
|
css::uno::Reference< css::awt::XMessageBox > xMsgBox(
|
|
ImplCreateWindow( aDescriptor, nAddWinBits ), css::uno::UNO_QUERY );
|
|
css::uno::Reference< css::awt::XWindow > xWindow( xMsgBox, css::uno::UNO_QUERY );
|
|
if ( xMsgBox.is() && xWindow.is() )
|
|
{
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if ( pWindow )
|
|
{
|
|
SolarMutexGuard aGuard;
|
|
xMsgBox->setCaptionText( aTitle );
|
|
xMsgBox->setMessageText( aMessage );
|
|
}
|
|
}
|
|
|
|
return xMsgBox;
|
|
}
|
|
|
|
css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > SAL_CALL VCLXToolkit::getDragGestureRecognizer( const css::uno::Reference< css::awt::XWindow >& window )
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( window );
|
|
|
|
if( pWindow )
|
|
return pWindow->GetDragGestureRecognizer();
|
|
|
|
return css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer >();
|
|
}
|
|
|
|
css::uno::Reference< css::datatransfer::dnd::XDragSource > SAL_CALL VCLXToolkit::getDragSource( const css::uno::Reference< css::awt::XWindow >& window )
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( window );
|
|
|
|
if( pWindow )
|
|
return pWindow->GetDragSource();
|
|
|
|
return css::uno::Reference< css::datatransfer::dnd::XDragSource >();
|
|
}
|
|
|
|
css::uno::Reference< css::datatransfer::dnd::XDropTarget > SAL_CALL VCLXToolkit::getDropTarget( const css::uno::Reference< css::awt::XWindow >& window )
|
|
{
|
|
SolarMutexGuard g;
|
|
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( window );
|
|
|
|
if( pWindow )
|
|
return pWindow->GetDropTarget();
|
|
|
|
return css::uno::Reference< css::datatransfer::dnd::XDropTarget >();
|
|
}
|
|
|
|
css::uno::Reference< css::datatransfer::clipboard::XClipboard > SAL_CALL VCLXToolkit::getClipboard( const OUString& clipboardName )
|
|
{
|
|
if( clipboardName.isEmpty() )
|
|
{
|
|
if( !mxClipboard.is() )
|
|
{
|
|
// remember clipboard here
|
|
mxClipboard = css::datatransfer::clipboard::SystemClipboard::create(
|
|
comphelper::getProcessComponentContext());
|
|
}
|
|
|
|
return mxClipboard;
|
|
}
|
|
|
|
else if( clipboardName == "Selection" )
|
|
{
|
|
return mxSelection;
|
|
}
|
|
|
|
return css::uno::Reference< css::datatransfer::clipboard::XClipboard >();
|
|
}
|
|
|
|
// XServiceInfo
|
|
OUString VCLXToolkit::getImplementationName()
|
|
{
|
|
return "stardiv.Toolkit.VCLXToolkit";
|
|
}
|
|
|
|
sal_Bool VCLXToolkit::supportsService( const OUString& rServiceName )
|
|
{
|
|
return cppu::supportsService(this, rServiceName);
|
|
}
|
|
|
|
css::uno::Sequence< OUString > VCLXToolkit::getSupportedServiceNames()
|
|
{
|
|
return css::uno::Sequence<OUString>{
|
|
"com.sun.star.awt.Toolkit", "stardiv.vcl.VclToolkit"};
|
|
}
|
|
|
|
// css::awt::XExtendedToolkit:
|
|
|
|
// virtual
|
|
::sal_Int32 SAL_CALL VCLXToolkit::getTopWindowCount()
|
|
{
|
|
return static_cast< ::sal_Int32 >(::Application::GetTopWindowCount());
|
|
// XXX numeric overflow
|
|
}
|
|
|
|
// virtual
|
|
css::uno::Reference< css::awt::XTopWindow > SAL_CALL
|
|
VCLXToolkit::getTopWindow(::sal_Int32 nIndex)
|
|
{
|
|
vcl::Window * p = ::Application::GetTopWindow(static_cast< tools::Long >(nIndex));
|
|
// XXX numeric overflow
|
|
return css::uno::Reference< css::awt::XTopWindow >(
|
|
p == nullptr ? nullptr : static_cast< css::awt::XWindow * >(p->GetWindowPeer()),
|
|
css::uno::UNO_QUERY);
|
|
}
|
|
|
|
// virtual
|
|
css::uno::Reference< css::awt::XTopWindow > SAL_CALL
|
|
VCLXToolkit::getActiveTopWindow()
|
|
{
|
|
vcl::Window * p = ::Application::GetActiveTopWindow();
|
|
return css::uno::Reference< css::awt::XTopWindow >(
|
|
p == nullptr ? nullptr : static_cast< css::awt::XWindow * >(p->GetWindowPeer()),
|
|
css::uno::UNO_QUERY);
|
|
}
|
|
|
|
// virtual
|
|
void SAL_CALL VCLXToolkit::addTopWindowListener(
|
|
css::uno::Reference< css::awt::XTopWindowListener > const & rListener)
|
|
{
|
|
OSL_ENSURE(rListener.is(), "Null rListener");
|
|
::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
|
|
if (rBHelper.bDisposed || rBHelper.bInDispose)
|
|
{
|
|
aGuard.clear();
|
|
rListener->disposing(
|
|
css::lang::EventObject(
|
|
getXWeak()));
|
|
}
|
|
else if (m_aTopWindowListeners.addInterface(rListener) == 1
|
|
&& !m_bEventListener)
|
|
{
|
|
m_bEventListener = true;
|
|
::Application::AddEventListener(m_aEventListenerLink);
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void SAL_CALL VCLXToolkit::removeTopWindowListener(
|
|
css::uno::Reference< css::awt::XTopWindowListener > const & rListener)
|
|
{
|
|
::osl::MutexGuard aGuard(rBHelper.rMutex);
|
|
if (!(rBHelper.bDisposed || rBHelper.bInDispose)
|
|
&& m_aTopWindowListeners.removeInterface(rListener) == 0
|
|
&& m_aFocusListeners.getLength() == 0 && m_bEventListener)
|
|
{
|
|
::Application::RemoveEventListener(m_aEventListenerLink);
|
|
m_bEventListener = false;
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void SAL_CALL VCLXToolkit::addKeyHandler(
|
|
css::uno::Reference< css::awt::XKeyHandler > const & rHandler)
|
|
{
|
|
OSL_ENSURE(rHandler.is(), "Null rHandler");
|
|
::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
|
|
if (rBHelper.bDisposed || rBHelper.bInDispose)
|
|
{
|
|
aGuard.clear();
|
|
rHandler->disposing(
|
|
css::lang::EventObject(
|
|
getXWeak()));
|
|
}
|
|
else if (m_aKeyHandlers.addInterface(rHandler) == 1 && !m_bKeyListener)
|
|
{
|
|
m_bKeyListener = true;
|
|
::Application::AddKeyListener(m_aKeyListenerLink);
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void SAL_CALL VCLXToolkit::removeKeyHandler(
|
|
css::uno::Reference< css::awt::XKeyHandler > const & rHandler)
|
|
{
|
|
::osl::MutexGuard aGuard(rBHelper.rMutex);
|
|
if (!(rBHelper.bDisposed || rBHelper.bInDispose)
|
|
&& m_aKeyHandlers.removeInterface(rHandler) == 0 && m_bKeyListener)
|
|
{
|
|
::Application::RemoveKeyListener(m_aKeyListenerLink);
|
|
m_bKeyListener = false;
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void SAL_CALL VCLXToolkit::addFocusListener(
|
|
css::uno::Reference< css::awt::XFocusListener > const & rListener)
|
|
{
|
|
OSL_ENSURE(rListener.is(), "Null rListener");
|
|
::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
|
|
if (rBHelper.bDisposed || rBHelper.bInDispose)
|
|
{
|
|
aGuard.clear();
|
|
rListener->disposing(
|
|
css::lang::EventObject(
|
|
getXWeak()));
|
|
}
|
|
else if (m_aFocusListeners.addInterface(rListener) == 1
|
|
&& !m_bEventListener)
|
|
{
|
|
m_bEventListener = true;
|
|
::Application::AddEventListener(m_aEventListenerLink);
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void SAL_CALL VCLXToolkit::removeFocusListener(
|
|
css::uno::Reference< css::awt::XFocusListener > const & rListener)
|
|
{
|
|
::osl::MutexGuard aGuard(rBHelper.rMutex);
|
|
if (!(rBHelper.bDisposed || rBHelper.bInDispose)
|
|
&& m_aFocusListeners.removeInterface(rListener) == 0
|
|
&& m_aTopWindowListeners.getLength() == 0 && m_bEventListener)
|
|
{
|
|
::Application::RemoveEventListener(m_aEventListenerLink);
|
|
m_bEventListener = false;
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void SAL_CALL VCLXToolkit::fireFocusGained(
|
|
css::uno::Reference<
|
|
css::uno::XInterface > const &)
|
|
{
|
|
}
|
|
|
|
// virtual
|
|
void SAL_CALL VCLXToolkit::fireFocusLost(
|
|
css::uno::Reference<
|
|
css::uno::XInterface > const &)
|
|
{
|
|
}
|
|
|
|
|
|
IMPL_LINK(VCLXToolkit, eventListenerHandler, ::VclSimpleEvent&, rEvent, void)
|
|
{
|
|
switch (rEvent.GetId())
|
|
{
|
|
case VclEventId::WindowShow:
|
|
callTopWindowListeners(
|
|
&rEvent, &css::awt::XTopWindowListener::windowOpened);
|
|
break;
|
|
case VclEventId::WindowHide:
|
|
callTopWindowListeners(
|
|
&rEvent, &css::awt::XTopWindowListener::windowClosed);
|
|
break;
|
|
case VclEventId::WindowActivate:
|
|
callTopWindowListeners(
|
|
&rEvent, &css::awt::XTopWindowListener::windowActivated);
|
|
break;
|
|
case VclEventId::WindowDeactivate:
|
|
callTopWindowListeners(
|
|
&rEvent, &css::awt::XTopWindowListener::windowDeactivated);
|
|
break;
|
|
case VclEventId::WindowClose:
|
|
callTopWindowListeners(
|
|
&rEvent, &css::awt::XTopWindowListener::windowClosing);
|
|
break;
|
|
case VclEventId::WindowGetFocus:
|
|
callFocusListeners(&rEvent, true);
|
|
break;
|
|
case VclEventId::WindowLoseFocus:
|
|
callFocusListeners(&rEvent, false);
|
|
break;
|
|
case VclEventId::WindowMinimize:
|
|
callTopWindowListeners(
|
|
&rEvent, &css::awt::XTopWindowListener::windowMinimized);
|
|
break;
|
|
case VclEventId::WindowNormalize:
|
|
callTopWindowListeners(
|
|
&rEvent, &css::awt::XTopWindowListener::windowNormalized);
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
IMPL_LINK(VCLXToolkit, keyListenerHandler, ::VclWindowEvent&, rEvent, bool)
|
|
{
|
|
switch (rEvent.GetId())
|
|
{
|
|
case VclEventId::WindowKeyInput:
|
|
return callKeyHandlers(&rEvent, true);
|
|
case VclEventId::WindowKeyUp:
|
|
return callKeyHandlers(&rEvent, false);
|
|
default: break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void VCLXToolkit::callTopWindowListeners(
|
|
::VclSimpleEvent const * pEvent,
|
|
void (SAL_CALL css::awt::XTopWindowListener::* pFn)(
|
|
css::lang::EventObject const &))
|
|
{
|
|
vcl::Window * pWindow
|
|
= static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow();
|
|
if (!pWindow->IsTopWindow())
|
|
return;
|
|
|
|
std::vector< css::uno::Reference< css::awt::XTopWindowListener > >
|
|
aListeners(m_aTopWindowListeners.getElements());
|
|
if (aListeners.empty())
|
|
return;
|
|
|
|
css::lang::EventObject aAwtEvent(
|
|
static_cast< css::awt::XWindow * >(pWindow->GetWindowPeer()));
|
|
for (const css::uno::Reference<css::awt::XTopWindowListener> & xListener : aListeners)
|
|
{
|
|
try
|
|
{
|
|
(xListener.get()->*pFn)(aAwtEvent);
|
|
}
|
|
catch (const css::uno::RuntimeException &)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("toolkit");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool VCLXToolkit::callKeyHandlers(::VclSimpleEvent const * pEvent,
|
|
bool bPressed)
|
|
{
|
|
std::vector< css::uno::Reference< css::awt::XKeyHandler > >
|
|
aHandlers(m_aKeyHandlers.getElements());
|
|
|
|
if (!aHandlers.empty())
|
|
{
|
|
vcl::Window * pWindow = static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow();
|
|
|
|
// See implementation in vclxwindow.cxx for mapping between VCL and UNO AWT event
|
|
::KeyEvent * pKeyEvent = static_cast< ::KeyEvent * >(
|
|
static_cast< ::VclWindowEvent const * >(pEvent)->GetData());
|
|
css::awt::KeyEvent aAwtEvent(
|
|
static_cast< css::awt::XWindow * >(pWindow->GetWindowPeer()),
|
|
(pKeyEvent->GetKeyCode().IsShift()
|
|
? css::awt::KeyModifier::SHIFT : 0)
|
|
| (pKeyEvent->GetKeyCode().IsMod1()
|
|
? css::awt::KeyModifier::MOD1 : 0)
|
|
| (pKeyEvent->GetKeyCode().IsMod2()
|
|
? css::awt::KeyModifier::MOD2 : 0)
|
|
| (pKeyEvent->GetKeyCode().IsMod3()
|
|
? css::awt::KeyModifier::MOD3 : 0),
|
|
pKeyEvent->GetKeyCode().GetCode(), pKeyEvent->GetCharCode(),
|
|
sal::static_int_cast< sal_Int16 >(
|
|
pKeyEvent->GetKeyCode().GetFunction()));
|
|
for (const css::uno::Reference<css::awt::XKeyHandler> & xHandler : aHandlers)
|
|
{
|
|
try
|
|
{
|
|
if (bPressed ? xHandler->keyPressed(aAwtEvent)
|
|
: xHandler->keyReleased(aAwtEvent))
|
|
return true;
|
|
}
|
|
catch (const css::uno::RuntimeException &)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("toolkit");
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void VCLXToolkit::callFocusListeners(::VclSimpleEvent const * pEvent,
|
|
bool bGained)
|
|
{
|
|
vcl::Window * pWindow
|
|
= static_cast< ::VclWindowEvent const * >(pEvent)->GetWindow();
|
|
if (!pWindow->IsTopWindow())
|
|
return;
|
|
|
|
std::vector< css::uno::Reference< css::awt::XFocusListener > >
|
|
aListeners(m_aFocusListeners.getElements());
|
|
if (aListeners.empty())
|
|
return;
|
|
|
|
// Ignore the interior of compound controls when determining the
|
|
// window that gets the focus next (see implementation in
|
|
// vclxwindow.cxx for mapping between VCL and UNO AWT event):
|
|
css::uno::Reference< css::uno::XInterface > xNext;
|
|
vcl::Window * pFocus = ::Application::GetFocusWindow();
|
|
for (vcl::Window * p = pFocus; p != nullptr; p = p->GetParent())
|
|
if (!p->IsCompoundControl())
|
|
{
|
|
pFocus = p;
|
|
break;
|
|
}
|
|
if (pFocus != nullptr)
|
|
xNext = pFocus->GetComponentInterface();
|
|
css::awt::FocusEvent aAwtEvent(
|
|
static_cast< css::awt::XWindow * >(pWindow->GetWindowPeer()),
|
|
static_cast<sal_Int16>(pWindow->GetGetFocusFlags()),
|
|
xNext, false);
|
|
for (const css::uno::Reference<css::awt::XFocusListener> & xListener : aListeners)
|
|
{
|
|
try
|
|
{
|
|
bGained ? xListener->focusGained(aAwtEvent)
|
|
: xListener->focusLost(aAwtEvent);
|
|
}
|
|
catch (const css::uno::RuntimeException &)
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("toolkit");
|
|
}
|
|
}
|
|
}
|
|
|
|
// css::awt::XReschedule:
|
|
|
|
void SAL_CALL VCLXToolkit::reschedule()
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
Application::Reschedule(true);
|
|
}
|
|
|
|
// css::awt::XFontMappingUse:
|
|
void SAL_CALL VCLXToolkit::startTrackingFontMappingUse()
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
OutputDevice::StartTrackingFontMappingUse();
|
|
}
|
|
|
|
css::uno::Sequence<css::awt::XFontMappingUseItem>
|
|
SAL_CALL VCLXToolkit::finishTrackingFontMappingUse()
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
OutputDevice::FontMappingUseData data = OutputDevice::FinishTrackingFontMappingUse();
|
|
css::uno::Sequence<css::awt::XFontMappingUseItem> ret( data.size());
|
|
css::awt::XFontMappingUseItem* retData = ret.getArray();
|
|
for( size_t i = 0; i < data.size(); ++i )
|
|
{
|
|
retData[ i ].originalFont = data[ i ].mOriginalFont;
|
|
retData[ i ].usedFonts = comphelper::arrayToSequence<OUString,OUString>
|
|
(data[ i ].mUsedFonts.data(), data[ i ].mUsedFonts.size());
|
|
retData[ i ].count = data[ i ].mCount;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// css::awt::XToolkitExperimental
|
|
|
|
void SAL_CALL VCLXToolkit::processEventsToIdle()
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
comphelper::ProfileZone aZone("processEvents");
|
|
Scheduler::ProcessEventsToIdle();
|
|
}
|
|
|
|
sal_Int64 SAL_CALL VCLXToolkit::getOpenGLBufferSwapCounter()
|
|
{
|
|
#if HAVE_FEATURE_OPENGL
|
|
return OpenGLWrapper::getBufferSwapCounter();
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
void SAL_CALL VCLXToolkit::setDeterministicScheduling(sal_Bool bDeterministicMode)
|
|
{
|
|
SolarMutexGuard aSolarGuard;
|
|
Scheduler::SetDeterministicMode(bDeterministicMode);
|
|
}
|
|
|
|
void SAL_CALL VCLXToolkit::pause(sal_Int32 nMilliseconds)
|
|
{
|
|
new Pause(nMilliseconds);
|
|
}
|
|
|
|
void SAL_CALL VCLXToolkit::startRecording()
|
|
{
|
|
comphelper::TraceEvent::startRecording();
|
|
}
|
|
|
|
void SAL_CALL VCLXToolkit::stopRecording()
|
|
{
|
|
comphelper::TraceEvent::stopRecording();
|
|
}
|
|
|
|
css::uno::Sequence< OUString > VCLXToolkit::getRecordingAndClear()
|
|
{
|
|
return comphelper::ProfileZone::getRecordingAndClear();
|
|
}
|
|
|
|
void VCLXToolkit::waitUntilAllIdlesDispatched()
|
|
{
|
|
IdleTask::waitUntilIdleDispatched();
|
|
}
|
|
|
|
// css:awt:XToolkitRobot
|
|
|
|
void SAL_CALL VCLXToolkit::keyPress( const css::awt::KeyEvent & aKeyEvent )
|
|
{
|
|
css::uno::Reference<css::awt::XWindow> xWindow ( aKeyEvent.Source, css::uno::UNO_QUERY_THROW );
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if( !pWindow )
|
|
throw css::uno::RuntimeException( "invalid event source" );
|
|
|
|
::KeyEvent aVCLKeyEvent = VCLUnoHelper::createVCLKeyEvent( aKeyEvent );
|
|
::Application::PostKeyEvent( VclEventId::WindowKeyInput, pWindow, &aVCLKeyEvent );
|
|
}
|
|
|
|
void SAL_CALL VCLXToolkit::keyRelease( const css::awt::KeyEvent & aKeyEvent )
|
|
{
|
|
css::uno::Reference<css::awt::XWindow> xWindow ( aKeyEvent.Source, css::uno::UNO_QUERY_THROW );
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if( !pWindow )
|
|
throw css::uno::RuntimeException( "invalid event source" );
|
|
|
|
::KeyEvent aVCLKeyEvent = VCLUnoHelper::createVCLKeyEvent( aKeyEvent );
|
|
::Application::PostKeyEvent( VclEventId::WindowKeyUp, pWindow, &aVCLKeyEvent );
|
|
}
|
|
|
|
|
|
void SAL_CALL VCLXToolkit::mousePress( const css::awt::MouseEvent & aMouseEvent )
|
|
{
|
|
css::uno::Reference<css::awt::XWindow> xWindow ( aMouseEvent.Source, css::uno::UNO_QUERY_THROW );
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if( !pWindow )
|
|
throw css::uno::RuntimeException( "invalid event source" );
|
|
|
|
::MouseEvent aVCLMouseEvent = VCLUnoHelper::createVCLMouseEvent( aMouseEvent );
|
|
::Application::PostMouseEvent( VclEventId::WindowMouseButtonDown, pWindow, &aVCLMouseEvent );
|
|
}
|
|
|
|
void SAL_CALL VCLXToolkit::mouseRelease( const css::awt::MouseEvent & aMouseEvent )
|
|
{
|
|
css::uno::Reference<css::awt::XWindow> xWindow ( aMouseEvent.Source, css::uno::UNO_QUERY_THROW );
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if( !pWindow )
|
|
throw css::uno::RuntimeException( "invalid event source" );
|
|
|
|
::MouseEvent aVCLMouseEvent = VCLUnoHelper::createVCLMouseEvent( aMouseEvent );
|
|
::Application::PostMouseEvent( VclEventId::WindowMouseButtonUp, pWindow, &aVCLMouseEvent );
|
|
}
|
|
|
|
void SAL_CALL VCLXToolkit::mouseMove( const css::awt::MouseEvent & aMouseEvent )
|
|
{
|
|
css::uno::Reference<css::awt::XWindow> xWindow ( aMouseEvent.Source, css::uno::UNO_QUERY_THROW );
|
|
VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow );
|
|
if( !pWindow )
|
|
throw css::uno::RuntimeException( "invalid event source" );
|
|
|
|
::MouseEvent aVCLMouseEvent = VCLUnoHelper::createVCLMouseEvent( aMouseEvent );
|
|
::Application::PostMouseEvent( VclEventId::WindowMouseMove, pWindow, &aVCLMouseEvent );
|
|
}
|
|
|
|
|
|
}
|
|
|
|
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
|
|
stardiv_Toolkit_VCLXToolkit_get_implementation(
|
|
css::uno::XComponentContext *,
|
|
css::uno::Sequence<css::uno::Any> const &)
|
|
{
|
|
return cppu::acquire(new VCLXToolkit());
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|