Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/toolkit/source/awt/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 98 kB image not shown  

Quelle  vclxtoolkit.cxx

  Sprache: 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/unohelp.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/MenuButton.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&&nbsp;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&&nbsp;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&&nbsp;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 >&&nbsp;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&&nbsp;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 eType = ImplGetComponentType( aServiceName );
    bool bFrameControl = false;
    if ( aServiceName == "frame" )
        bFrameControl = true;
    if ( aServiceName == "tabcontrolnotabs" )
    {
        nWinBits |= WB_NOBORDER;
        eType = 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  (   ( eType == WindowType::DIALOG )
            ||  ( eType == WindowType::MODELESSDIALOG )
            ||  ( eType == WindowType::MESSBOX )
            ||  ( eType == WindowType::INFOBOX )
            ||  ( eType == WindowType::WARNINGBOX )
            ||  ( eType == WindowType::ERRORBOX )
            ||  ( eType == WindowType::QUERYBOX )
            )
            bException = false;
        else if ( ( eType == WindowType::WINDOW ) ||
                  ( eType == WindowType::WORKWINDOW ) ||
                  ( eType == WindowType::TOOLKIT_FRAMEWINDOW ) )
        {
            if ( rDescriptor.Type == css::awt::WindowClass_TOP )
                bException = false;
        }

        if ( bException )
        {
            *ppNewComp = nullptr;
            return nullptr;
        }
    }

    if ( eType != WindowType::NONE )
    {
        SolarMutexGuard aVclGuard;
        switch ( eType )
        {
            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 VCLXWindow;
            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 (eType == 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 (eType == WindowType::DOCKINGWINDOW )
                        pNewWindow = VclPtr<DockingWindow>::Create( pParent, nWinBits );
                    else
                        pNewWindow = VclPtr<vcl::Window>::Create( pParent, nWinBits );
                    *ppNewComp = new VCLXContainer;
                }
                else
                {
                    if (eType == 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 = vcl::unohelper::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.reset();
            }
        }
    }
    else if (nSystemType == css::lang::SystemDependent::SYSTEM_JAVA)
    {
        SolarMutexGuard aGuard;
        pChildWindow.reset(VclPtr<WorkWindow>::Create(nullptr, Parent));
    }

    if ( !pChildWindow )
        return nullptr;

    rtl::Reference<VCLXTopWindow> pPeer = new VCLXTopWindow;
    SolarMutexGuard aGuard;
    pPeer->SetWindow( pChildWindow );
    pChildWindow->SetWindowPeer(pPeer, pPeer.get());

    return pPeer;
}

// 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;
    defaultbreak;
    }
}

IMPL_LINK(VCLXToolkit, keyListenerHandler, ::VclWindowEvent&, rEvent, bool)
{
    switch (rEvent.GetId())
    {
    case VclEventId::WindowKeyInput:
        return callKeyHandlers(&rEvent, true);
    case VclEventId::WindowKeyUp:
        return callKeyHandlers(&rEvent, false);
    defaultbreak;
    }
    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: */

Messung V0.5 in Prozent
C=96 H=99 G=97

¤ Dauer der Verarbeitung: 0.36 Sekunden  (vorverarbeitet am  2026-05-05) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.