    /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
    /*
     * This file is part of the LibreOffice project.
     *
     * This Source Code Form is subject to the terms of the Mozilla Public
     * License, v. 2.0. If a copy of the MPL was not distributed with this
     * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     *
     * This file incorporates work covered by the following license notice:
     *
     *   Licensed to the Apache Software Foundation (ASF) under one or more
     *   contributor license agreements. See the NOTICE file distributed
     *   with this work for additional information regarding copyright
     *   ownership. The ASF licenses this file to you under the Apache
     *   License, Version 2.0 (the "License"); you may not use this file
     *   except in compliance with the License. You may obtain a copy of
     *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
     */

    #include <config_features.h>

    #include <com/sun/star/beans/XPropertySet.hpp>
    #include <com/sun/star/util/thePathSettings.hpp>
    #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
    #include <comphelper/lok.hxx>
    #include <comphelper/scopeguard.hxx>
    #include <comphelper/processfactory.hxx>
    #include <officecfg/Office/Common.hxx>
    #include <osl/file.hxx>

    #include <tools/debug.hxx>

    #include <svdata.hxx>
    #include <window.h>
    #include <brdwin.hxx>

    #include <rtl/bootstrap.hxx>
    #include <rtl/strbuf.hxx>
    #include <sal/log.hxx>

    #include <vcl/abstdlg.hxx>
    #include <vcl/builder.hxx>
    #include <vcl/layout.hxx>
    #include <vcl/svapp.hxx>
    #include <vcl/event.hxx>
    #include <vcl/wrkwin.hxx>
    #include <vcl/button.hxx>
    #include <vcl/mnemonic.hxx>
    #include <vcl/dialog.hxx>
    #include <vcl/tabctrl.hxx>
    #include <vcl/tabpage.hxx>
    #include <vcl/decoview.hxx>
    #include <vcl/unowrap.hxx>
    #include <vcl/settings.hxx>
    #include <vcl/uitest/uiobject.hxx>
    #include <vcl/uitest/logger.hxx>
    #include <vcl/virdev.hxx>
    #include <vcl/IDialogRenderable.hxx>
    #include <messagedialog.hxx>
    #include <salframe.hxx>

    #include <iostream>
    #include <utility>

    static OString ImplGetDialogText( Dialog* pDialog )
    {
        OStringBuffer aErrorStr(OUStringToOString(
            pDialog->GetText(), RTL_TEXTENCODING_UTF8));

        OUString sMessage;
        if (MessageDialog* pMessDialog = dynamic_cast<MessageDialog*>(pDialog))
        {
            sMessage = pMessDialog->get_primary_text();
        }

        if (!sMessage.isEmpty())
        {
            aErrorStr.append(", ");
            aErrorStr.append(OUStringToOString(
                sMessage, RTL_TEXTENCODING_UTF8));
        }
        return aErrorStr.makeStringAndClear();
    }

    static bool ImplIsMnemonicCtrl( vcl::Window* pWindow )
    {
        if( ! pWindow->GetSettings().GetStyleSettings().GetAutoMnemonic() )
            return false;

        if ( (pWindow->GetType() == WindowType::RADIOBUTTON) ||
             (pWindow->GetType() == WindowType::CHECKBOX) ||
             (pWindow->GetType() == WindowType::TRISTATEBOX) ||
             (pWindow->GetType() == WindowType::PUSHBUTTON) )
            return true;

        if ( pWindow->GetType() == WindowType::FIXEDTEXT )
        {
            FixedText *pText = static_cast<FixedText*>(pWindow);
            if (pText->get_mnemonic_widget())
                return true;
            //This is the legacy pre-layout logic which we retain
            //until we can be sure we can remove it
            if (pWindow->GetStyle() & WB_NOLABEL)
                return false;
            vcl::Window* pNextWindow = pWindow->GetWindow( GetWindowType::Next );
            if ( !pNextWindow )
                return false;
            pNextWindow = pNextWindow->GetWindow( GetWindowType::Client );
            return !(!(pNextWindow->GetStyle() & WB_TABSTOP) ||
                     (pNextWindow->GetType() == WindowType::FIXEDTEXT) ||
                     (pNextWindow->GetType() == WindowType::GROUPBOX) ||
                     (pNextWindow->GetType() == WindowType::RADIOBUTTON) ||
                     (pNextWindow->GetType() == WindowType::CHECKBOX) ||
                     (pNextWindow->GetType() == WindowType::TRISTATEBOX) ||
                     (pNextWindow->GetType() == WindowType::PUSHBUTTON));
        }

        return false;
    }

    // Called by native error dialog popup implementations
    void ImplHideSplash()
    {
        ImplSVData* pSVData = ImplGetSVData();
        if( pSVData->mpIntroWindow )
                pSVData->mpIntroWindow->Hide();
    }

    //Get next window after pChild of a pTopLevel window as
    //if any intermediate layout widgets didn't exist
    vcl::Window * nextLogicalChildOfParent(vcl::Window *pTopLevel, vcl::Window *pChild)
    {
        vcl::Window *pLastChild = pChild;

        if (isContainerWindow(*pChild))
            pChild = pChild->GetWindow(GetWindowType::FirstChild);
        else
            pChild = pChild->GetWindow(GetWindowType::Next);

        while (!pChild)
        {
            vcl::Window *pParent = pLastChild->GetParent();
            if (!pParent)
                return nullptr;
            if (pParent == pTopLevel)
                return nullptr;
            pLastChild = pParent;
            pChild = pParent->GetWindow(GetWindowType::Next);
        }

        if (pChild && isContainerWindow(*pChild))
            pChild = nextLogicalChildOfParent(pTopLevel, pChild);

        return pChild;
    }

    vcl::Window * prevLogicalChildOfParent(vcl::Window *pTopLevel, vcl::Window *pChild)
    {
        vcl::Window *pLastChild = pChild;

        if (isContainerWindow(*pChild))
            pChild = pChild->GetWindow(GetWindowType::LastChild);
        else
            pChild = pChild->GetWindow(GetWindowType::Prev);

        while (!pChild)
        {
            vcl::Window *pParent = pLastChild->GetParent();
            if (!pParent)
                return nullptr;
            if (pParent == pTopLevel)
                return nullptr;
            pLastChild = pParent;
            pChild = pParent->GetWindow(GetWindowType::Prev);
        }

        if (pChild && isContainerWindow(*pChild))
            pChild = prevLogicalChildOfParent(pTopLevel, pChild);

        return pChild;
    }

    //Get first window of a pTopLevel window as
    //if any intermediate layout widgets didn't exist
    vcl::Window * firstLogicalChildOfParent(vcl::Window *pTopLevel)
    {
        vcl::Window *pChild = pTopLevel->GetWindow(GetWindowType::FirstChild);
        if (pChild && isContainerWindow(*pChild))
            pChild = nextLogicalChildOfParent(pTopLevel, pChild);
        return pChild;
    }

    void Accelerator::GenerateAutoMnemonicsOnHierarchy(vcl::Window* pWindow)
    {
        MnemonicGenerator   aMnemonicGenerator;
        vcl::Window*                 pGetChild;
        vcl::Window*                 pChild;

        // register the assigned mnemonics
        pGetChild = pWindow->GetWindow( GetWindowType::FirstChild );
        while ( pGetChild )
        {
            pChild = pGetChild->ImplGetWindow();
            aMnemonicGenerator.RegisterMnemonic( pChild->GetText() );
            pGetChild = nextLogicalChildOfParent(pWindow, pGetChild);
        }

        // take the Controls of the dialog into account for TabPages
        if ( pWindow->GetType() == WindowType::TABPAGE )
        {
            vcl::Window* pParent = pWindow->GetParent();
            if ( pParent->GetType() == WindowType::TABCONTROL )
                pParent = pParent->GetParent();

            if ( (pParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL )
            {
                pGetChild = pParent->GetWindow( GetWindowType::FirstChild );
                while ( pGetChild )
                {
                    pChild = pGetChild->ImplGetWindow();
                    aMnemonicGenerator.RegisterMnemonic( pChild->GetText() );
                    pGetChild = nextLogicalChildOfParent(pWindow, pGetChild);
                }
            }
        }

        // assign mnemonics to Controls which have none
        pGetChild = pWindow->GetWindow( GetWindowType::FirstChild );
        while ( pGetChild )
        {
            pChild = pGetChild->ImplGetWindow();
            if ( ImplIsMnemonicCtrl( pChild ) )
            {
                OUString aText = pChild->GetText();
                OUString aNewText = aMnemonicGenerator.CreateMnemonic( aText );
                if ( aText != aNewText )
                    pChild->SetText( aNewText );
            }

            pGetChild = nextLogicalChildOfParent(pWindow, pGetChild);
        }
    }

    static VclButtonBox* getActionArea(Dialog const *pDialog)
    {
        VclButtonBox *pButtonBox = nullptr;
        if (pDialog->isLayoutEnabled())
        {
            vcl::Window *pBox = pDialog->GetWindow(GetWindowType::FirstChild);
            vcl::Window *pChild = pBox->GetWindow(GetWindowType::LastChild);
            while (pChild)
            {
                pButtonBox = dynamic_cast<VclButtonBox*>(pChild);
                if (pButtonBox)
                    break;
                pChild = pChild->GetWindow(GetWindowType::Prev);
            }
        }
        return pButtonBox;
    }

    static vcl::Window* getActionAreaButtonList(Dialog const *pDialog)
    {
        VclButtonBox* pButtonBox = getActionArea(pDialog);
        if (pButtonBox)
            return pButtonBox->GetWindow(GetWindowType::FirstChild);
        return pDialog->GetWindow(GetWindowType::FirstChild);
    }

    static PushButton* ImplGetDefaultButton( Dialog const * pDialog )
    {
        vcl::Window* pChild = getActionAreaButtonList(pDialog);
        while ( pChild )
        {
            if ( pChild->ImplIsPushButton() )
            {
                PushButton* pPushButton = static_cast<PushButton*>(pChild);
                if ( pPushButton->ImplIsDefButton() )
                    return pPushButton;
            }

            pChild = pChild->GetWindow( GetWindowType::Next );
        }

        return nullptr;
    }

    static PushButton* ImplGetOKButton( Dialog const * pDialog )
    {
        vcl::Window* pChild = getActionAreaButtonList(pDialog);
        while ( pChild )
        {
            if ( pChild->GetType() == WindowType::OKBUTTON )
                return static_cast<PushButton*>(pChild);

            pChild = pChild->GetWindow( GetWindowType::Next );
        }

        return nullptr;
    }

    static PushButton* ImplGetCancelButton( Dialog const * pDialog )
    {
        vcl::Window* pChild = getActionAreaButtonList(pDialog);

        while ( pChild )
        {
            if ( pChild->GetType() == WindowType::CANCELBUTTON )
                return static_cast<PushButton*>(pChild);

            pChild = pChild->GetWindow( GetWindowType::Next );
        }

        return nullptr;
    }

    static void ImplMouseAutoPos( Dialog* pDialog )
    {
        MouseSettingsOptions nMouseOptions = pDialog->GetSettings().GetMouseSettings().GetOptions();
        if ( nMouseOptions & MouseSettingsOptions::AutoCenterPos )
        {
            Size aSize = pDialog->GetOutputSizePixel();
            pDialog->SetPointerPosPixel( Point( aSize.Width()/2, aSize.Height()/2 ) );
        }
        else if ( nMouseOptions & MouseSettingsOptions::AutoDefBtnPos )
        {
            vcl::Window* pWindow = ImplGetDefaultButton( pDialog );
            if ( !pWindow )
                pWindow = ImplGetOKButton( pDialog );
            if ( !pWindow )
                pWindow = ImplGetCancelButton( pDialog );
            if ( !pWindow )
                pWindow = pDialog;
            Size aSize = pWindow->GetOutputSizePixel();
            pWindow->SetPointerPosPixel( Point( aSize.Width()/2, aSize.Height()/2 ) );
        }
    }

    struct DialogImpl
    {
        std::vector<VclPtr<PushButton>> maOwnedButtons;
        std::map<VclPtr<vcl::Window>, short> maResponses;
        long    mnResult;
        bool    mbStartedModal;
        VclAbstractDialog::AsyncContext maEndCtx;

        DialogImpl() : mnResult( -1 ), mbStartedModal( false ) {}

    #ifndef NDEBUG
        short get_response(vcl::Window *pWindow) const
        {
            auto aFind = maResponses.find(pWindow);
            if (aFind != maResponses.end())
                return aFind->second;
            return RET_CANCEL;
        }
    #endif

        ~DialogImpl()
        {
            for (VclPtr<PushButton> & pOwnedButton : maOwnedButtons)
                pOwnedButton.disposeAndClear();
        }
    };

    void Dialog::disposeOwnedButtons()
    {
        for (VclPtr<PushButton> & pOwnedButton : mpDialogImpl->maOwnedButtons)
            pOwnedButton.disposeAndClear();
    }

    void Dialog::ImplInitDialogData()
    {
        mpWindowImpl->mbDialog  = true;
        mbInExecute             = false;
        mbInSyncExecute         = false;
        mbInClose               = false;
        mbModalMode             = false;
        mbPaintComplete         = false;
        mpContentArea.clear();
        mpActionArea.clear();
        mnMousePositioned       = 0;
        mpDialogImpl.reset(new DialogImpl);
    }

    vcl::Window* Dialog::GetDefaultParent(WinBits nStyle)
    {
        vcl::Window* pParent = Application::GetDefDialogParent();
        if (!pParent && !(nStyle & WB_SYSTEMWINDOW))
            pParent = ImplGetSVData()->maWinData.mpAppWin;

        // If Parent is disabled, then we search for a modal dialog
        // in this frame
        if (pParent && (!pParent->IsInputEnabled() || pParent->IsInModalMode()))
        {
            ImplSVData* pSVData = ImplGetSVData();
            auto& rExecuteDialogs = pSVData->maWinData.mpExecuteDialogs;
            for (auto it = rExecuteDialogs.rbegin(); it != rExecuteDialogs.rend(); ++it)
            {
                // only if visible and enabled
                if (pParent->ImplGetFirstOverlapWindow()->IsWindowOrChild(*it, true) &&
                    (*it)->IsReallyVisible() &&
                    (*it)->IsEnabled() && (*it)->IsInputEnabled() && !(*it)->IsInModalMode())
                {
                    pParent = it->get();
                    break;
                }
            }
        }

        return pParent;
    }

    VclPtr<vcl::Window> Dialog::AddBorderWindow(vcl::Window* pParent, WinBits nStyle)
    {
        VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle, BorderWindowStyle::Frame );
        SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, nullptr );
        pBorderWin->mpWindowImpl->mpClientWindow = this;
        pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
        mpWindowImpl->mpBorderWindow  = pBorderWin;
        mpWindowImpl->mpRealParent    = pParent;

        return pBorderWin;
    }

    void Dialog::ImplInit( vcl::Window* pParent, WinBits nStyle, InitFlag eFlag )
    {
        SystemWindowFlags nSysWinMode = Application::GetSystemWindowMode();

        if ( !(nStyle & WB_NODIALOGCONTROL) )
            nStyle |= WB_DIALOGCONTROL;
        nStyle |= WB_ROLLABLE;

        // Now, all Dialogs are per default system windows !!!
        nStyle |= WB_SYSTEMWINDOW;

        if (InitFlag::NoParent == eFlag)
        {
            pParent = nullptr;
        }
        else if (!pParent) // parent is NULL: get the default Dialog parent
        {
            pParent = Dialog::GetDefaultParent(nStyle);
        }

        if ( !pParent || (nStyle & WB_SYSTEMWINDOW) ||
             (pParent->mpWindowImpl->mpFrameData->mbNeedSysWindow && !(nSysWinMode & SystemWindowFlags::NOAUTOMODE)) ||
             (nSysWinMode & SystemWindowFlags::DIALOG) )
        {
            // create window with a small border ?
            if (mbForceBorderWindow || ((nStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE)) == WB_BORDER ))
            {
                AddBorderWindow(pParent, nStyle);
            }
            else
            {
                mpWindowImpl->mbFrame         = true;
                mpWindowImpl->mbOverlapWin    = true;
                SystemWindow::ImplInit( pParent, (nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_STANDALONE)) | WB_CLOSEABLE, nullptr );
                // Now set all style bits
                mpWindowImpl->mnStyle = nStyle;
            }
        }
        else
        {
            VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle, BorderWindowStyle::Overlap | BorderWindowStyle::Border );
            SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, nullptr );
            pBorderWin->mpWindowImpl->mpClientWindow = this;
            pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
            mpWindowImpl->mpBorderWindow  = pBorderWin;
            mpWindowImpl->mpRealParent    = pParent;
        }

        SetActivateMode( ActivateModeFlags::GrabFocus );

        ImplInitSettings();
    }

    void Dialog::ApplySettings(vcl::RenderContext& rRenderContext)
    {
        if (IsControlBackground())
        {
            // user override
            SetBackground(GetControlBackground());
        }
        else if (rRenderContext.IsNativeControlSupported(ControlType::WindowBackground, ControlPart::BackgroundDialog))
        {
            // NWF background
            mpWindowImpl->mnNativeBackground = ControlPart::BackgroundDialog;
            EnableChildTransparentMode();
        }
        else
        {
            // fallback to settings color
            rRenderContext.SetBackground(GetSettings().GetStyleSettings().GetDialogColor());
        }
    }

    void Dialog::ImplInitSettings()
    {
        // user override
        if (IsControlBackground())
            SetBackground(GetControlBackground());
        // NWF background
        else if( IsNativeControlSupported(ControlType::WindowBackground, ControlPart::BackgroundDialog))
        {
            mpWindowImpl->mnNativeBackground = ControlPart::BackgroundDialog;
            EnableChildTransparentMode();
        }
        // fallback to settings color
        else
            SetBackground(GetSettings().GetStyleSettings().GetDialogColor());
    }

    void Dialog::ImplLOKNotifier(vcl::Window* pParent)
    {
        if (comphelper::LibreOfficeKit::isActive() && pParent)
        {
            if (VclPtr<vcl::Window> pWin = pParent->GetParentWithLOKNotifier())
            {
                SetLOKNotifier(pWin->GetLOKNotifier());
            }
        }
    }

    Dialog::Dialog( WindowType nType )
        : SystemWindow( nType )
        , mbForceBorderWindow(false)
        , mnInitFlag(InitFlag::Default)
    {
        ImplInitDialogData();
    }

    void VclBuilderContainer::disposeBuilder()
    {
        if (m_pUIBuilder)
            m_pUIBuilder->disposeBuilder();
    }

    OUString VclBuilderContainer::getUIRootDir()
    {
        OUString sShareLayer("$BRAND_BASE_DIR/$BRAND_SHARE_SUBDIR/config/soffice.cfg/");
        rtl::Bootstrap::expandMacros(sShareLayer);
        return sShareLayer;
    }

    //we can't change sizeable after the fact, so need to defer until we know and then
    //do the init. Find the real parent stashed in mpDialogParent.
    void Dialog::doDeferredInit(WinBits nBits)
    {
        VclPtr<vcl::Window> pParent = mpDialogParent;
        mpDialogParent = nullptr;
        ImplInit(pParent, nBits | WB_BORDER, mnInitFlag);
        mbIsDeferredInit = false;
    }

    Dialog::Dialog(vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription)
        : SystemWindow(WindowType::DIALOG)
        , mbForceBorderWindow(false)
        , mnInitFlag(InitFlag::Default)
    {
        ImplLOKNotifier(pParent);
        ImplInitDialogData();
        loadUI(pParent, OUStringToOString(rID, RTL_TEXTENCODING_UTF8), rUIXMLDescription);
    }

    Dialog::Dialog(vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription, WindowType nType, InitFlag eFlag, bool bBorder)
        : SystemWindow(nType)
        , mbForceBorderWindow(bBorder)
        , mnInitFlag(eFlag)
    {
        ImplLOKNotifier(pParent);
        ImplInitDialogData();
        loadUI(pParent, OUStringToOString(rID, RTL_TEXTENCODING_UTF8), rUIXMLDescription);
    }

    Dialog::Dialog(vcl::Window* pParent, WinBits nStyle, InitFlag eFlag)
        : SystemWindow(WindowType::DIALOG)
        , mbForceBorderWindow(false)
        , mnInitFlag(eFlag)
    {
        ImplLOKNotifier(pParent);
        ImplInitDialogData();
        ImplInit( pParent, nStyle, eFlag );
    }

    void Dialog::set_action_area(VclButtonBox* pBox)
    {
        mpActionArea.set(pBox);
        if (pBox)
        {
            const DialogStyle& rDialogStyle =
                GetSettings().GetStyleSettings().GetDialogStyle();
            pBox->set_border_width(rDialogStyle.action_area_border);
        }
    }

    void Dialog::set_content_area(VclBox* pBox)
    {
        mpContentArea.set(pBox);
    }

    void Dialog::settingOptimalLayoutSize(Window *pBox)
    {
        const DialogStyle& rDialogStyle =
            GetSettings().GetStyleSettings().GetDialogStyle();
        VclBox * pBox2 = static_cast<VclBox*>(pBox);
        pBox2->set_border_width(rDialogStyle.content_area_border);
        pBox2->set_spacing(pBox2->get_spacing() +
            rDialogStyle.content_area_spacing);
    }

    Dialog::~Dialog()
    {
        disposeOnce();
    }

    void Dialog::dispose()
    {
        mpDialogImpl.reset();
        RemoveFromDlgList();
        mpActionArea.clear();
        mpContentArea.clear();

        css::uno::Reference< css::uno::XComponentContext > xContext(
                comphelper::getProcessComponentContext() );
        css::uno::Reference<css::frame::XGlobalEventBroadcaster> xEventBroadcaster(css::frame::theGlobalEventBroadcaster::get(xContext), css::uno::UNO_QUERY_THROW);
        css::document::DocumentEvent aObject;
        aObject.EventName = "DialogClosed";
        xEventBroadcaster->documentEventOccured(aObject);
        UITestLogger::getInstance().log("DialogClosed");

        if (comphelper::LibreOfficeKit::isActive())
        {
            if(const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
            {
                pNotifier->notifyWindow(GetLOKWindowId(), "close");
                ReleaseLOKNotifier();
            }
        }

        SystemWindow::dispose();
    }

    IMPL_LINK_NOARG(Dialog, ImplAsyncCloseHdl, void*, void)
    {
        Close();
    }

    bool Dialog::EventNotify( NotifyEvent& rNEvt )
    {
        // first call the base class due to Tab control
        bool bRet = SystemWindow::EventNotify( rNEvt );
        if ( !bRet )
        {
            if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
            {
                const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
                vcl::KeyCode    aKeyCode = pKEvt->GetKeyCode();
                sal_uInt16      nKeyCode = aKeyCode.GetCode();

                if ( (nKeyCode == KEY_ESCAPE) &&
                     ((GetStyle() & WB_CLOSEABLE) || ImplGetCancelButton( this ) || ImplGetOKButton( this )) )
                {
                    // #i89505# for the benefit of slightly mentally challenged implementations
                    // like e.g. SfxModelessDialog which destroy themselves inside Close()
                    // post this Close asynchronous so we can leave our key handler before
                    // we get destroyed
                    PostUserEvent( LINK( this, Dialog, ImplAsyncCloseHdl ), nullptr, true);
                    return true;
                }
            }
            else if ( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
            {
                // make sure the dialog is still modal
                // changing focus between application frames may
                // have re-enabled input for our parent
                if( mbInExecute && mbModalMode )
                {
                    ImplSetModalInputMode( false );
                    ImplSetModalInputMode( true );

                    // #93022# def-button might have changed after show
                    if( !mnMousePositioned )
                    {
                        mnMousePositioned = 1;
                        ImplMouseAutoPos( this );
                    }

                }
            }
        }

        return bRet;
    }

    //What we really want here is something that gives the available width and
    //height of a users screen, taking away the space taken up the OS
    //taskbar, menus, etc.
    Size bestmaxFrameSizeForScreenSize(const Size &rScreenSize)
    {
        long w = rScreenSize.Width();
        if (w <= 800)
            w -= 15;
        else if (w <= 1024)
            w -= 65;
        else
            w -= 115;

        long h = rScreenSize.Height();
        if (h <= 768)
            h -= 50;
        else
            h -= 100;

        return Size(std::max<long>(w, 640 - 15),
                    std::max<long>(h, 480 - 50));
    }

    void Dialog::StateChanged( StateChangedType nType )
    {
        if (nType == StateChangedType::InitShow)
        {
            DoInitialLayout();

            if ( !HasChildPathFocus() || HasFocus() )
                GrabFocusToFirstControl();
            if ( !(GetStyle() & WB_CLOSEABLE) )
            {
                if ( ImplGetCancelButton( this ) || ImplGetOKButton( this ) )
                {
                    if ( ImplGetBorderWindow() )
                        static_cast<ImplBorderWindow*>(ImplGetBorderWindow())->SetCloseButton();
                }
            }

            ImplMouseAutoPos( this );
        }
        else if (nType == StateChangedType::Text)
        {
            if (const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
            {
                std::vector<vcl::LOKPayloadItem> aPayload;
                aPayload.emplace_back("title", GetText().toUtf8());
                pNotifier->notifyWindow(GetLOKWindowId(), "title_changed", aPayload);
            }
        }

        SystemWindow::StateChanged( nType );

        if (nType == StateChangedType::ControlBackground)
        {
            ImplInitSettings();
            Invalidate();
        }
    }

    void Dialog::DataChanged( const DataChangedEvent& rDCEvt )
    {
        SystemWindow::DataChanged( rDCEvt );

        if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
             (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
        {
            ImplInitSettings();
            Invalidate();
        }
    }

    bool Dialog::Close()
    {
        VclPtr<vcl::Window> xWindow = this;
        CallEventListeners( VclEventId::WindowClose );
        if ( xWindow->IsDisposed() )
            return false;

        if ( mpWindowImpl->mxWindowPeer.is() && IsCreatedWithToolkit() && !IsInExecute() )
            return false;

        mbInClose = true;

        if ( !(GetStyle() & WB_CLOSEABLE) )
        {
            bool bRet = true;
            PushButton* pButton = ImplGetCancelButton( this );
            if ( pButton )
                pButton->Click();
            else
            {
                pButton = ImplGetOKButton( this );
                if ( pButton )
                    pButton->Click();
                else
                    bRet = false;
            }
            if ( xWindow->IsDisposed() )
                return true;
            return bRet;
        }

        if ( IsInExecute() )
        {
            EndDialog();
            mbInClose = false;
            return true;
        }
        else
        {
            mbInClose = false;
            return SystemWindow::Close();
        }
    }

    bool Dialog::ImplStartExecuteModal()
    {
        setDeferredProperties();

        if ( mbInExecute || mpDialogImpl->maEndCtx.isSet() )
        {
    #ifdef DBG_UTIL
            SAL_WARN( "vcl", "Dialog::StartExecuteModal() is called in Dialog::StartExecuteModal(): "
                        << ImplGetDialogText(this) );
    #endif
            return false;
        }

        ImplSVData* pSVData = ImplGetSVData();

        switch ( Application::GetDialogCancelMode() )
        {
        case Application::DialogCancelMode::Off:
            break;
        case Application::DialogCancelMode::Silent:
            if (GetLOKNotifier())
            {
                // check if there's already some dialog being ::Execute()d
                const bool bDialogExecuting = std::any_of(pSVData->maWinData.mpExecuteDialogs.begin(),
                                                          pSVData->maWinData.mpExecuteDialogs.end(),
                                                          [](const Dialog* pDialog) {
                                                              return pDialog->IsInSyncExecute();
                                                          });
                if (!(bDialogExecuting && IsInSyncExecute()))
                    break;
                else
                    SAL_WARN("lok.dialog", "Dialog \"" << ImplGetDialogText(this) << "\" is being synchronously executed over an existing synchronously executing dialog.");
            }

            SAL_INFO(
                "vcl",
                "Dialog \"" << ImplGetDialogText(this)
                    << "\"cancelled in silent mode");
            return false;
        default: // default cannot happen
        case Application::DialogCancelMode::Fatal:
            std::abort();
        }

    #ifdef DBG_UTIL
        vcl::Window* pParent = GetParent();
        if ( pParent )
        {
            pParent = pParent->ImplGetFirstOverlapWindow();
            SAL_WARN_IF( !pParent->IsReallyVisible(), "vcl",
                        "Dialog::StartExecuteModal() - Parent not visible" );
            SAL_WARN_IF( !pParent->IsInputEnabled(), "vcl",
                        "Dialog::StartExecuteModal() - Parent input disabled, use another parent to ensure modality!" );
            SAL_WARN_IF(  pParent->IsInModalMode(), "vcl",
                        "Dialog::StartExecuteModal() - Parent already modally disabled, use another parent to ensure modality!" );

        }
    #endif

        // link all dialogs which are being executed
        pSVData->maWinData.mpExecuteDialogs.push_back(this);

        // stop capturing, in order to have control over the dialog
        if ( pSVData->maWinData.mpTrackWin )
            pSVData->maWinData.mpTrackWin->EndTracking( TrackingEventFlags::Cancel );
        if ( pSVData->maWinData.mpCaptureWin )
            pSVData->maWinData.mpCaptureWin->ReleaseMouse();
        EnableInput();

        if ( GetParent() )
        {
            NotifyEvent aNEvt( MouseNotifyEvent::EXECUTEDIALOG, this );
            GetParent()->CompatNotify( aNEvt );
        }
        mbInExecute = true;
        // no real modality in LibreOfficeKit
        if (!comphelper::LibreOfficeKit::isActive())
            SetModalInputMode(true);

        // FIXME: no layouting, workaround some clipping issues
        ImplAdjustNWFSizes();

        css::uno::Reference< css::uno::XComponentContext > xContext(
            comphelper::getProcessComponentContext());
        bool bForceFocusAndToFront(officecfg::Office::Common::View::NewDocumentHandling::ForceFocusAndToFront::get(xContext));
        ShowFlags showFlags = bForceFocusAndToFront ? ShowFlags::ForegroundTask : ShowFlags::NONE;
        Show(true, showFlags);

        pSVData->maAppData.mnModalMode++;

        css::uno::Reference<css::frame::XGlobalEventBroadcaster> xEventBroadcaster(css::frame::theGlobalEventBroadcaster::get(xContext), css::uno::UNO_QUERY_THROW);
        css::document::DocumentEvent aObject;
        aObject.EventName = "DialogExecute";
        xEventBroadcaster->documentEventOccured(aObject);
        UITestLogger::getInstance().log("ModalDialogExecuted Id:" + get_id());

        if (comphelper::LibreOfficeKit::isActive())
        {
            if(const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
            {
                std::vector<vcl::LOKPayloadItem> aItems;
                aItems.emplace_back("type", "dialog");
                aItems.emplace_back("size", GetSizePixel().toString());
                if (!GetText().isEmpty())
                    aItems.emplace_back("title", GetText().toUtf8());
                pNotifier->notifyWindow(GetLOKWindowId(), "created", aItems);
            }
        }

        return true;
    }

    void Dialog::ImplEndExecuteModal()
    {
        ImplSVData* pSVData = ImplGetSVData();
        pSVData->maAppData.mnModalMode--;
    }

    void Dialog::PrePaint(vcl::RenderContext& rRenderContext)
    {
        SystemWindow::PrePaint(rRenderContext);
        mbPaintComplete = false;
    }

    void Dialog::PostPaint(vcl::RenderContext& rRenderContext)
    {
        SystemWindow::PostPaint(rRenderContext);
        mbPaintComplete = true;
    }

    std::vector<OString> Dialog::getAllPageUIXMLDescriptions() const
    {
        // default has no pages
        return std::vector<OString>();
    }

    bool Dialog::selectPageByUIXMLDescription(const OString& /*rUIXMLDescription*/)
    {
        // default cannot select anything (which is okay, return true)
        return true;
    }

    void Dialog::ensureRepaint()
    {
        // ensure repaint
        Invalidate();
        mbPaintComplete = false;

        while (!mbPaintComplete)
        {
            Application::Yield();
        }
    }

    BitmapEx Dialog::createScreenshot()
    {
        // same prerequisites as in Execute()
        setDeferredProperties();
        ImplAdjustNWFSizes();
        Show();
        ToTop();
        ensureRepaint();

        return GetBitmapEx(Point(), GetOutputSizePixel());
    }

    short Dialog::Execute()
    {
    #if HAVE_FEATURE_DESKTOP
        VclPtr<vcl::Window> xWindow = this;

        mbInSyncExecute = true;
        comphelper::ScopeGuard aGuard([&]() {
                mbInSyncExecute = false;
            });

        if ( !ImplStartExecuteModal() )
            return 0;

        // Yield util EndDialog is called or dialog gets destroyed
        // (the latter should not happen, but better safe than sorry
        while ( !xWindow->IsDisposed() && mbInExecute )
            Application::Yield();

        ImplEndExecuteModal();
    #ifdef DBG_UTIL
        assert (!mpDialogParent || !mpDialogParent->IsDisposed());
    #endif
        if ( !xWindow->IsDisposed() )
            xWindow.clear();
    #ifdef DBG_UTIL
        else
        {
            OSL_FAIL( "Dialog::Execute() - Dialog destroyed in Execute()" );
        }
    #endif

        long nRet = mpDialogImpl->mnResult;
        mpDialogImpl->mnResult = -1;

        return static_cast<short>(nRet);

    #else

        // touch_ui_dialog_modal was dummied out both for Android and iOS (well, TiledLibreOffice anyway)
        // For Android it returned MLODialogOK always, for iOS Cancel. Let's go with OK.
        // MLODialogResult result = touch_ui_dialog_modal(kind, ImplGetDialogText(this).getStr());
        return RET_OK;

    #endif
    }

    // virtual
    void Dialog::StartExecuteModal( const Link<Dialog&,void>& rEndDialogHdl )
    {
        VclAbstractDialog::AsyncContext aCtx;
        VclPtr<Dialog> ref(this);
        aCtx.maEndDialogFn = [ref,rEndDialogHdl](sal_Int32){ rEndDialogHdl.Call(*ref.get()); };
        StartExecuteAsync(aCtx);
    }

    // virtual
    bool Dialog::StartExecuteAsync( VclAbstractDialog::AsyncContext &rCtx )
    {
        if ( !ImplStartExecuteModal() )
        {
            rCtx.mxOwner.disposeAndClear();
            rCtx.mxOwnerDialog.reset();
            return false;
        }

        mpDialogImpl->maEndCtx = rCtx;
        mpDialogImpl->mbStartedModal = true;

        return true;
    }

    void Dialog::RemoveFromDlgList()
    {
        ImplSVData* pSVData = ImplGetSVData();
        auto& rExecuteDialogs = pSVData->maWinData.mpExecuteDialogs;

        // remove dialog from the list of dialogs which are being executed
        rExecuteDialogs.erase(std::remove_if(rExecuteDialogs.begin(), rExecuteDialogs.end(), [=](VclPtr<Dialog>& dialog){ return dialog.get() == this; }), rExecuteDialogs.end());
    }

    void Dialog::EndDialog( long nResult )
    {
        if ( !mbInExecute )
            return;

        SetModalInputMode(false);

        RemoveFromDlgList();

        // set focus to previous modal dialogue if it is modal for
        // the same frame parent (or NULL)
        ImplSVData* pSVData = ImplGetSVData();
        if (!pSVData->maWinData.mpExecuteDialogs.empty())
        {
            VclPtr<Dialog> pPrevious = pSVData->maWinData.mpExecuteDialogs.back();

            vcl::Window* pFrameParent = ImplGetFrameWindow()->ImplGetParent();
            vcl::Window* pPrevFrameParent = pPrevious->ImplGetFrameWindow()? pPrevious->ImplGetFrameWindow()->ImplGetParent(): nullptr;
            if( ( !pFrameParent && !pPrevFrameParent ) ||
                ( pFrameParent && pPrevFrameParent && pFrameParent->ImplGetFrame() == pPrevFrameParent->ImplGetFrame() )
                )
            {
                pPrevious->GrabFocus();
            }
        }

        Hide();
        if ( GetParent() )
        {
            NotifyEvent aNEvt( MouseNotifyEvent::ENDEXECUTEDIALOG, this );
            GetParent()->CompatNotify( aNEvt );
        }

        mpDialogImpl->mnResult = nResult;

        if ( mpDialogImpl->mbStartedModal )
        {
            ImplEndExecuteModal();
            if (mpDialogImpl->maEndCtx.isSet())
            {
                mpDialogImpl->maEndCtx.maEndDialogFn(nResult);
                mpDialogImpl->maEndCtx.maEndDialogFn = nullptr;
            }
            mpDialogImpl->mbStartedModal = false;
            mpDialogImpl->mnResult = -1;
        }
        mbInExecute = false;

        // Destroy ourselves (if we have a context with VclPtr owner)
        std::shared_ptr<weld::DialogController> xOwnerDialog = std::move(mpDialogImpl->maEndCtx.mxOwnerDialog);
        mpDialogImpl->maEndCtx.mxOwner.disposeAndClear();
        xOwnerDialog.reset();
    }

    long Dialog::GetResult() const
    {
        return mpDialogImpl->mnResult;
    }

    void Dialog::EndAllDialogs( vcl::Window const * pParent )
    {
        ImplSVData* pSVData = ImplGetSVData();
        auto& rExecuteDialogs = pSVData->maWinData.mpExecuteDialogs;

        for (auto it = rExecuteDialogs.rbegin(); it != rExecuteDialogs.rend(); ++it)
        {
            if (!pParent || pParent->IsWindowOrChild(*it, true))
            {
                (*it)->EndDialog();
                (*it)->PostUserEvent(Link<void*, void>());
            }
        }
    }

    VclPtr<Dialog> Dialog::GetMostRecentExecutingDialog()
    {
        ImplSVData* pSVData = ImplGetSVData();
        auto& rExecuteDialogs = pSVData->maWinData.mpExecuteDialogs;
        if (!rExecuteDialogs.empty())
            return rExecuteDialogs.back();
        return nullptr;
    }

    void Dialog::SetModalInputMode( bool bModal )
    {
        if ( bModal == mbModalMode )
            return;

        ImplGetFrame()->SetModal(bModal);
        ImplSetModalInputMode(bModal);
    }

    void Dialog::ImplSetModalInputMode( bool bModal )
    {
        if ( bModal == mbModalMode )
            return;

        // previously Execute()'d dialog - the one below the top-most one
        VclPtr<Dialog> pPrevious;
        ImplSVData* pSVData = ImplGetSVData();
        auto& rExecuteDialogs = pSVData->maWinData.mpExecuteDialogs;
        if (rExecuteDialogs.size() > 1)
            pPrevious = rExecuteDialogs[rExecuteDialogs.size() - 2];

        mbModalMode = bModal;
        if ( bModal )
        {
            // Disable the prev Modal Dialog, because our dialog must close at first,
            // before the other dialog can be closed (because the other dialog
            // is on stack since our dialog returns)
            if (pPrevious && !pPrevious->IsWindowOrChild(this, true))
                pPrevious->EnableInput(false, this);

            // determine next overlap dialog parent
            vcl::Window* pParent = GetParent();
            if ( pParent )
            {
                // #103716# dialogs should always be modal to the whole frame window
                // #115933# disable the whole frame hierarchy, useful if our parent
                // is a modeless dialog
                mpDialogParent = pParent->mpWindowImpl->mpFrameWindow;
                mpDialogParent->IncModalCount();
            }
        }
        else
        {
            if ( mpDialogParent )
            {
                // #115933# re-enable the whole frame hierarchy again (see above)
                // note that code in getfocus assures that we do not accidentally enable
                // windows that were disabled before
                mpDialogParent->DecModalCount();
            }

            // Enable the prev Modal Dialog
            if (pPrevious && !pPrevious->IsWindowOrChild(this, true))
            {
                pPrevious->EnableInput(true, this);

                // ensure continued modality of prev dialog
                // do not change modality counter

                // #i119994# need find the last modal dialog before reactive it
                if (pPrevious->IsModalInputMode() || !pPrevious->IsWindowOrChild(this, true))
                {
                    pPrevious->ImplSetModalInputMode(false);
                    pPrevious->ImplSetModalInputMode(true);
                }
            }
        }
    }

    void Dialog::GrabFocusToFirstControl()
    {
        vcl::Window* pFocusControl;

        // find focus control, even if the dialog has focus
        if ( HasFocus() )
            pFocusControl = nullptr;
        else
        {
            // prefer a child window which had focus before
            pFocusControl = ImplGetFirstOverlapWindow()->mpWindowImpl->mpLastFocusWindow;
            // find the control out of the dialog control
            if ( pFocusControl )
                pFocusControl = ImplFindDlgCtrlWindow( pFocusControl );
        }
        // no control had the focus before or the control is not
        // part of the tab-control, now give focus to the
        // first control in the tab-control
        if ( !pFocusControl ||
             !(pFocusControl->GetStyle() & WB_TABSTOP) ||
             !isVisibleInLayout(pFocusControl) ||
             !isEnabledInLayout(pFocusControl) || !pFocusControl->IsInputEnabled() )
        {
            pFocusControl = ImplGetDlgWindow( 0, GetDlgWindowType::First );
        }
        if ( pFocusControl )
            pFocusControl->ImplControlFocus( GetFocusFlags::Init );
    }

    void Dialog::GetDrawWindowBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const
    {
        ScopedVclPtrInstance<ImplBorderWindow> aImplWin( static_cast<vcl::Window*>(const_cast<Dialog *>(this)), WB_BORDER|WB_STDWORK, BorderWindowStyle::Overlap );
        aImplWin->GetBorder( rLeftBorder, rTopBorder, rRightBorder, rBottomBorder );
    }

    void Dialog::Draw( OutputDevice* pDev, const Point& rPos, const Size& rSize, DrawFlags )
    {
        Point aPos = pDev->LogicToPixel( rPos );
        Size aSize = pDev->LogicToPixel( rSize );

        Wallpaper aWallpaper = GetBackground();
        if ( !aWallpaper.IsBitmap() )
            ImplInitSettings();

        pDev->Push();
        pDev->SetMapMode();
        pDev->SetLineColor();

        if ( aWallpaper.IsBitmap() )
            pDev->DrawBitmapEx( aPos, aSize, aWallpaper.GetBitmap() );
        else
        {
            pDev->SetFillColor( aWallpaper.GetColor() );
            pDev->DrawRect( tools::Rectangle( aPos, aSize ) );
        }

        if (!( GetStyle() & WB_NOBORDER ))
        {
            ScopedVclPtrInstance< ImplBorderWindow > aImplWin( this, WB_BORDER|WB_STDWORK, BorderWindowStyle::Overlap );
            aImplWin->SetText( GetText() );
            aImplWin->setPosSizePixel( aPos.X(), aPos.Y(), aSize.Width(), aSize.Height() );
            aImplWin->SetDisplayActive( true );
            aImplWin->InitView();

            aImplWin->Draw( pDev, aPos );
        }

        pDev->Pop();
    }

    void Dialog::queue_resize(StateChangedType eReason)
    {
        if (IsInClose())
            return;
        SystemWindow::queue_resize(eReason);
    }

    void Dialog::Resize()
    {
        SystemWindow::Resize();

        if (comphelper::LibreOfficeKit::isDialogPainting())
            return;

        if (const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
        {
            std::vector<vcl::LOKPayloadItem> aItems;
            aItems.emplace_back("size", GetSizePixel().toString());
            pNotifier->notifyWindow(GetLOKWindowId(), "size_changed", aItems);
        }
    }

    bool Dialog::set_property(const OString &rKey, const OUString &rValue)
    {
        if (rKey == "border-width")
            set_border_width(rValue.toInt32());
        else
            return SystemWindow::set_property(rKey, rValue);
        return true;
    }

    FactoryFunction Dialog::GetUITestFactory() const
    {
        return DialogUIObject::create;
    }

    IMPL_LINK(Dialog, ResponseHdl, Button*, pButton, void)
    {
        auto aFind = mpDialogImpl->maResponses.find(pButton);
        if (aFind == mpDialogImpl->maResponses.end())
            return;
        short nResponse = aFind->second;
        if (nResponse == RET_HELP)
        {
            vcl::Window* pFocusWin = Application::GetFocusWindow();
            if (!pFocusWin)
                pFocusWin = pButton;
            HelpEvent aEvt(pFocusWin->GetPointerPosPixel(), HelpEventMode::CONTEXT);
            pFocusWin->RequestHelp(aEvt);
            return;
        }
        EndDialog(nResponse);
    }

    void Dialog::add_button(PushButton* pButton, int response, bool bTransferOwnership)
    {
        if (bTransferOwnership)
            mpDialogImpl->maOwnedButtons.push_back(pButton);
        mpDialogImpl->maResponses[pButton] = response;
        switch (pButton->GetType())
        {
            case WindowType::PUSHBUTTON:
            {
                if (!pButton->GetClickHdl().IsSet())
                    pButton->SetClickHdl(LINK(this, Dialog, ResponseHdl));
                break;
            }
            //insist that the response ids match the default actions for those
            //widgets, and leave their default handlers in place
            case WindowType::OKBUTTON:
                assert(mpDialogImpl->get_response(pButton) == RET_OK);
                break;
            case WindowType::CANCELBUTTON:
                assert(mpDialogImpl->get_response(pButton) == RET_CANCEL || mpDialogImpl->get_response(pButton) == RET_CLOSE);
                break;
            case WindowType::HELPBUTTON:
                assert(mpDialogImpl->get_response(pButton) == RET_HELP);
                break;
            default:
                SAL_WARN("vcl.layout", "The type of widget " <<
                    pButton->GetHelpId() << " is currently not handled");
                break;
        }
    }

    vcl::Window* Dialog::get_widget_for_response(int response)
    {
        //copy explicit responses
        std::map<VclPtr<vcl::Window>, short> aResponses(mpDialogImpl->maResponses);

        //add implicit responses
        for (vcl::Window* pChild = mpActionArea->GetWindow(GetWindowType::FirstChild); pChild;
             pChild = pChild->GetWindow(GetWindowType::Next))
        {
            if (aResponses.find(pChild) != aResponses.end())
                continue;
            switch (pChild->GetType())
            {
                case WindowType::OKBUTTON:
                    aResponses[pChild] = RET_OK;
                    break;
                case WindowType::CANCELBUTTON:
                    aResponses[pChild] = RET_CANCEL;
                    break;
                case WindowType::HELPBUTTON:
                    aResponses[pChild] = RET_HELP;
                    break;
                default:
                    break;
            }
        }

        for (auto& a : aResponses)
        {
            if (a.second == response)
               return a.first;
        }

        return nullptr;
    }

    void Dialog::set_default_response(int response)
    {
        //copy explicit responses
        std::map<VclPtr<vcl::Window>, short> aResponses(mpDialogImpl->maResponses);

        //add implicit responses
        for (vcl::Window* pChild = mpActionArea->GetWindow(GetWindowType::FirstChild); pChild;
             pChild = pChild->GetWindow(GetWindowType::Next))
        {
            if (aResponses.find(pChild) != aResponses.end())
                continue;
            switch (pChild->GetType())
            {
                case WindowType::OKBUTTON:
                    aResponses[pChild] = RET_OK;
                    break;
                case WindowType::CANCELBUTTON:
                    aResponses[pChild] = RET_CANCEL;
                    break;
                case WindowType::HELPBUTTON:
                    aResponses[pChild] = RET_HELP;
                    break;
                default:
                    break;
            }
        }

        for (auto& a : aResponses)
        {
            if (a.second == response)
            {
                a.first->SetStyle(a.first->GetStyle() | WB_DEFBUTTON);
                a.first->GrabFocus();
            }
            else
            {
                a.first->SetStyle(a.first->GetStyle() & ~WB_DEFBUTTON);
            }
        }
    }

    VclBuilderContainer::VclBuilderContainer()
    {
    }

    VclBuilderContainer::~VclBuilderContainer()
    {
    }

    ModelessDialog::ModelessDialog(vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription, InitFlag eFlag)
        : Dialog(pParent, rID, rUIXMLDescription, WindowType::MODELESSDIALOG, eFlag)
    {
        UITestLogger::getInstance().log("ModelessDialogConstructed Id:" + get_id());
    }

    ModalDialog::ModalDialog( vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription, bool bBorder ) :
        Dialog(pParent, rID, rUIXMLDescription, WindowType::MODALDIALOG, InitFlag::Default, bBorder)
    {
    }

    void ModelessDialog::Activate()
    {
        css::uno::Reference< css::uno::XComponentContext > xContext(
                comphelper::getProcessComponentContext() );
        css::uno::Reference<css::frame::XGlobalEventBroadcaster> xEventBroadcaster(css::frame::theGlobalEventBroadcaster::get(xContext), css::uno::UNO_QUERY_THROW);
        css::document::DocumentEvent aObject;
        aObject.EventName = "ModelessDialogVisible";
        xEventBroadcaster->documentEventOccured(aObject);
        Dialog::Activate();
    }

    /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

↑ V560 A part of conditional expression is always true: pChild.

↑ V560 A part of conditional expression is always true: pChild.

↑ V776 Potentially infinite loop. The variable in the loop exit condition '!mbPaintComplete' does not change its value between iterations.