office-gobmx/toolkit/source/awt/vclxtoolkit.cxx
Michael Weghorn 2fdee9fd60 Unify/Port to use VCLUnoHelper for AWT <-> VCL conversions
Following

    Change-Id: Id48f81deb05aee2026509037f7d14575735e5be0
    Author: Michael Weghorn <m.weghorn@posteo.de>
    Date:   Wed Jul 10 14:49:03 2024 +0200

        VCLUnoHelper: Align AWT <-> VCL helpers with convert.hxx impl

, port all uses of the helper functions defined in
`include/toolkit/helper/convert.hxx` to use the
`VCLUnoHelper` equivalents instead, to unify usage
and avoid duplication.

Drop `include/toolkit/helper/convert.hxx` now that
it's unused.

Change-Id: I22695a93e40e47bb2b14d191a2e0a4eb7c856895
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170317
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2024-07-11 06:44:48 +02:00

2611 lines
98 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/bootstrap.hxx>
#include <comphelper/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 <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/lok.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <comphelper/interfacecontainer4.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 comphelper::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::OInterfaceContainerHelper4<css::awt::XTopWindowListener> m_aTopWindowListeners;
::comphelper::OInterfaceContainerHelper4<css::awt::XKeyHandler> m_aKeyHandlers;
::comphelper::OInterfaceContainerHelper4<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:
virtual void disposing(std::unique_lock<std::mutex>& rGuard) override;
static vcl::Window* ImplCreateWindow( rtl::Reference<VCLXWindow>* ppNewComp, const css::awt::WindowDescriptor& rDescriptor, vcl::Window* pParent,
WinBits nWinBits, MessBoxStyle nMessBoxStyle );
static 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():
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() &&
!comphelper::LibreOfficeKit::isActive() )
{
// setup execute thread
CreateMainLoopThread( ToolkitWorkerFunction, this );
getInitCondition().wait();
}
#endif
}
void VCLXToolkit::disposing(std::unique_lock<std::mutex>& rGuard)
{
#ifndef IOS
rGuard.unlock();
{
osl::Guard< osl::Mutex > aGuard( getInitMutex() );
if( --nVCLToolkitInstanceCount == 0 )
{
if( bInitedByVCLToolkit )
{
Application::Quit();
JoinMainLoopThread();
bInitedByVCLToolkit = false;
}
}
}
rGuard.lock();
#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(rGuard, aEvent);
m_aKeyHandlers.disposeAndClear(rGuard, aEvent);
m_aFocusListeners.disposeAndClear(rGuard, 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.GetWidth();
aNotherRect.Height = aWorkRect.GetHeight();
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 )
{
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( )
{
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(u"ID"_ustr);
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(u"Label"_ustr);
aValue >>= aCurRMItemData.Label;
aValue = xPropertySet->getPropertyValue(u"ID"_ustr);
aValue >>= aCurRMItemData.n_ID;
aValue = xPropertySet->getPropertyValue(u"Enabled"_ustr);
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( u"tabcontrol"_ustr );
}
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 : 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;
}
// static
css::uno::Reference< css::awt::XWindowPeer > VCLXToolkit::ImplCreateWindow(
const css::awt::WindowDescriptor& rDescriptor,
MessBoxStyle nForceMessBoxStyle )
{
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 = VCLUnoHelper::ConvertToVCLRect(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 )
{
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 : 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 u"stardiv.Toolkit.VCLXToolkit"_ustr;
}
sal_Bool VCLXToolkit::supportsService( const OUString& rServiceName )
{
return cppu::supportsService(this, rServiceName);
}
css::uno::Sequence< OUString > VCLXToolkit::getSupportedServiceNames()
{
return css::uno::Sequence<OUString>{
u"com.sun.star.awt.Toolkit"_ustr, u"stardiv.vcl.VclToolkit"_ustr};
}
// 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");
std::unique_lock aGuard(m_aMutex);
if (m_bDisposed)
{
aGuard.unlock();
rListener->disposing(
css::lang::EventObject(
getXWeak()));
}
else if (m_aTopWindowListeners.addInterface(aGuard, 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)
{
std::unique_lock aGuard(m_aMutex);
if (!m_bDisposed
&& m_aTopWindowListeners.removeInterface(aGuard, rListener) == 0
&& m_aFocusListeners.getLength(aGuard) == 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");
std::unique_lock aGuard(m_aMutex);
if (m_bDisposed)
{
aGuard.unlock();
rHandler->disposing(
css::lang::EventObject(
getXWeak()));
}
else if (m_aKeyHandlers.addInterface(aGuard, 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)
{
std::unique_lock aGuard(m_aMutex);
if (!m_bDisposed
&& m_aKeyHandlers.removeInterface(aGuard, 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");
std::unique_lock aGuard(m_aMutex);
if (m_bDisposed)
{
aGuard.unlock();
rListener->disposing(
css::lang::EventObject(
getXWeak()));
}
else if (m_aFocusListeners.addInterface(aGuard, 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)
{
std::unique_lock aGuard(m_aMutex);
if (!m_bDisposed
&& m_aFocusListeners.removeInterface(aGuard, rListener) == 0
&& m_aTopWindowListeners.getLength(aGuard) == 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::unique_lock aGuard(m_aMutex);
if (m_aTopWindowListeners.getLength(aGuard) == 0)
return;
css::lang::EventObject aAwtEvent(
static_cast< css::awt::XWindow * >(pWindow->GetWindowPeer()));
m_aTopWindowListeners.forEach(aGuard,
[&pFn, &aAwtEvent](const css::uno::Reference<css::awt::XTopWindowListener> & xListener)
{
try
{
(xListener.get()->*pFn)(aAwtEvent);
}
catch (const css::uno::RuntimeException &)
{
DBG_UNHANDLED_EXCEPTION("toolkit");
}
});
}
bool VCLXToolkit::callKeyHandlers(::VclSimpleEvent const * pEvent,
bool bPressed)
{
std::unique_lock aGuard(m_aMutex);
if (m_aKeyHandlers.getLength(aGuard) != 0)
{
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()));
comphelper::OInterfaceIteratorHelper4 aIt(aGuard, m_aKeyHandlers);
aGuard.unlock();
while (aIt.hasMoreElements())
{
css::awt::XKeyHandler* pL = aIt.next().get();
try
{
if (bPressed ? pL->keyPressed(aAwtEvent)
: pL->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::unique_lock aGuard(m_aMutex);
if (m_aFocusListeners.getLength(aGuard) == 0)
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);
m_aFocusListeners.forEach(aGuard,
[bGained, &aAwtEvent] (const css::uno::Reference<css::awt::XFocusListener> & xListener)
{
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( u"invalid event source"_ustr );
::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( u"invalid event source"_ustr );
::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( u"invalid event source"_ustr );
::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( u"invalid event source"_ustr );
::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( u"invalid event source"_ustr );
::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: */