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

Quelle  dialog.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 <config_feature_desktop.h>

#ifdef IOS
#include <premac.h>
#include <UIKit/UIKit.h>
#include <postmac.h>
#endif

#include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
#include <comphelper/lok.hxx>
#include <comphelper/scopeguard.hxx>
#include <comphelper/processfactory.hxx>
#include <o3tl/test_info.hxx>
#include <officecfg/Office/Common.hxx>
#include <osl/diagnose.h>

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

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

#include <vcl/abstdlg.hxx>
#include <vcl/builder.hxx>
#include <vcl/toolkit/floatwin.hxx>
#include <vcl/layout.hxx>
#include <vcl/svapp.hxx>
#include <vcl/event.hxx>
#include <vcl/locktoplevels.hxx>
#include <vcl/wrkwin.hxx>
#include <vcl/toolkit/button.hxx>
#include <vcl/mnemonic.hxx>
#include <vcl/toolkit/dialog.hxx>
#include <vcl/dialoghelper.hxx>
#include <vcl/settings.hxx>
#include <vcl/virdev.hxx>
#include <vcl/weld.hxx>
#include <vcl/uitest/uiobject.hxx>
#include <vcl/uitest/logger.hxx>
#include <vcl/IDialogRenderable.hxx>
#include <messagedialog.hxx>
#include <salframe.hxx>
#include <tools/json_writer.hxx>

#include <iostream>
#include <stack>
#include <utility>
#include <vector>

static OString ImplGetDialogText( Dialog* pDialog )
{
    OUString aErrorStr(pDialog->GetText());

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

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

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();
}

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

    if (pChild->GetType() == WindowType::SCROLLWINDOW)
        pChild = static_cast<const VclScrolledWindow*>(pChild)->get_child();
    else 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 (isContainerWindow(*pChild))
        pChild = nextLogicalChildOfParent(pTopLevel, pChild);

    return const_cast<vcl::Window *>(pChild);
}

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

    if (pChild->GetType() == WindowType::SCROLLWINDOW)
        pChild = static_cast<const VclScrolledWindow*>(pChild)->get_child();
    else 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 (isContainerWindow(*pChild))
        pChild = prevLogicalChildOfParent(pTopLevel, pChild);

    return const_cast<vcl::Window *>(pChild);
}

vcl::Window * firstLogicalChildOfParent(const vcl::Window *pTopLevel)
{
    const vcl::Window *pChild = pTopLevel->GetWindow(GetWindowType::FirstChild);
    if (pChild && isContainerWindow(*pChild))
        pChild = nextLogicalChildOfParent(pTopLevel, pChild);
    return const_cast<vcl::Window *>(pChild);
}

vcl::Window * lastLogicalChildOfParent(const vcl::Window *pTopLevel)
{
    const vcl::Window *pChild = pTopLevel->GetWindow(GetWindowType::LastChild);
    if (pChild && isContainerWindow(*pChild))
        pChild = prevLogicalChildOfParent(pTopLevel, pChild);
    return const_cast<vcl::Window *>(pChild);
}

void GenerateAutoMnemonicsOnHierarchy(const 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 && pParent->GetType() == WindowType::TABCONTROL )
            pParent = pParent->GetParent();

        if (pParent && (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;
    tools::Long    mnResult;
    bool    mbStartedModal;
    VclAbstractDialog::AsyncContext maEndCtx;
    Link<const CommandEvent&, bool> m_aPopupMenuHdl;
    Link<void*, vcl::ILibreOfficeKitNotifier*> m_aInstallLOKNotifierHdl;
    bool    m_bLOKTunneling;

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

#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()
    {
        disposeAndClear();
    }

    void disposeAndClear()
    {
        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;
    mpContentArea.reset();
    mpActionArea.reset();
    mnMousePositioned       = 0;
    mpDialogImpl.reset(new DialogImpl);
}

void Dialog::PixelInvalidate(const tools::Rectangle* pRectangle)
{
    if (!mpDialogImpl->m_bLOKTunneling)
        return;

    Window::PixelInvalidate(pRectangle);
}

vcl::Window* Dialog::GetDefaultParent(WinBits nStyle)
{
    vcl::Window* pParent = Dialog::GetDefDialogParent();
    if (!pParent && !(nStyle & WB_SYSTEMWINDOW))
        pParent = ImplGetSVData()->maFrameData.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->mpWinData->mpExecuteDialogs;
        auto it = std::find_if(rExecuteDialogs.rbegin(), rExecuteDialogs.rend(),
            [&pParent](VclPtr<Dialog>& rDialogPtr) {
                return pParent->ImplGetFirstOverlapWindow() &&
                    pParent->ImplGetFirstOverlapWindow()->IsWindowOrChild(rDialogPtr, true) &&
                    rDialogPtr->IsReallyVisible() && rDialogPtr->IsEnabled() &&
                    rDialogPtr->IsInputEnabled() && !rDialogPtr->IsInModalMode(); });
        if (it != rExecuteDialogs.rend())
            pParent = it->get();
    }

    return pParent;
}

VclPtr<vcl::Window> Dialog::AddBorderWindow(vcl::Window* pParent, WinBits nStyle)
{
    VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle, BorderWindowStyle::Frame );
    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::ImplInitDialog( vcl::Window* pParent, WinBits nStyle, InitFlag eFlag )
{
    SystemWindowFlags nSysWinMode = Application::GetSystemWindowMode();

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

    // 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 ((nStyle & WB_ALLOWMENUBAR) || ((nStyle & (WB_BORDER | WB_NOBORDER | WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE)) == WB_BORDER))
        {
            AddBorderWindow(pParent, nStyle);
        }
        else
        {
            mpWindowImpl->mbFrame         = true;
            mpWindowImpl->mbOverlapWin    = true;
            ImplInit( pParent, (nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_STANDALONE)) | WB_CLOSEABLE, nullptr );
            // Now set all style bits
            mpWindowImpl->mnStyle = nStyle;
        }
    }
    else
    {
        VclPtrInstance<ImplBorderWindow> pBorderWin( pParent, nStyle, BorderWindowStyle::Overlap );
        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 eType )
    : SystemWindow( eType, "vcl::Dialog maLayoutIdle"true )
    , mnInitFlag(InitFlag::Default)
{
    ImplInitDialogData();
}

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

OUString AllSettings::GetUIRootDir()
{
    OUString sShareLayer(u"$BRAND_BASE_DIR/$BRAND_SHARE_SUBDIR/config/soffice.cfg/"_ustr);
    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.
void Dialog::ImplDeferredInit(vcl::Window* pParent, WinBits nBits)
{
    ImplInitDialog(pParent, nBits | WB_BORDER, mnInitFlag);
}

Dialog::Dialog(vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription)
    : SystemWindow(WindowType::DIALOG, "vcl::Dialog maLayoutIdle"true)
    , mnInitFlag(InitFlag::Default)
{
    ImplLOKNotifier(pParent);
    ImplInitDialogData();
    loadUI(pParent, rID, rUIXMLDescription);
}

Dialog::Dialog(vcl::Window* pParent, WinBits nStyle, InitFlag eFlag)
    : SystemWindow(WindowType::DIALOG, "vcl::Dialog maLayoutIdle"true)
    , mnInitFlag(eFlag)
{
    ImplLOKNotifier(pParent);
    ImplInitDialogData();
    ImplInitDialog( pParent, nStyle, eFlag );
}

void Dialog::set_action_area(VclButtonBox* pBox)
{
    mpActionArea.reset(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.reset(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);
}

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

void Dialog::dispose()
{
    bool bTunnelingEnabled = mpDialogImpl->m_bLOKTunneling;

    mpDialogImpl->disposeAndClear();
    RemoveFromDlgList();
    mpActionArea.reset();
    mpContentArea.reset();

    const css::uno::Reference< css::uno::XComponentContext >& xContext(
            comphelper::getProcessComponentContext() );
    css::uno::Reference<css::frame::XGlobalEventBroadcaster> xEventBroadcaster(css::frame::theGlobalEventBroadcaster::get(xContext), css::uno::UNO_SET_THROW);
    css::document::DocumentEvent aObject;
    aObject.EventName = "DialogClosed";
    aObject.Supplement <<= GetText(); // title
    xEventBroadcaster->documentEventOccured(aObject);
    UITestLogger::getInstance().log(u"Close Dialog");

    if (comphelper::LibreOfficeKit::isActive())
    {
        if(const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
        {
            if (bTunnelingEnabled)
                pNotifier->notifyWindow(GetLOKWindowId(), u"close"_ustr);
            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() == NotifyEventType::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() == NotifyEventType::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)
{
#ifndef IOS
    tools::Long w = rScreenSize.Width();
    if (w <= 800)
        w -= 15;
    else if (w <= 1024)
        w -= 65;
    else
        w -= 115;

    tools::Long h = rScreenSize.Height();
    if (h <= 768)
        h -= 50;
    else
        h -= 100;

    return Size(std::max<tools::Long>(w, 640 - 15),
                std::max<tools::Long>(h, 480 - 50));
#else
    // Don't bother with ancient magic numbers of unclear relevance on non-desktop apps anyway. It
    // seems that at least currently in the iOS app, this function is called just once per dialog,
    // with a rScreenSize parameter of 1x1 (!). This would lead to always returning 625x430 which is
    // a bit random and needlessly small on an iPad at least. We want something that closely will
    // just fit on the display in either orientation.

    // We ignore the rScreenSize as it will be the dummy 1x1 from iosinst.cxx (see "Totally wrong of course").
    (void) rScreenSize;

    const int n = std::min<CGFloat>([[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height);
    return Size(n-10, n-10);
#endif
}

void Dialog::SetPopupMenuHdl(const Link<const CommandEvent&, bool>& rLink)
{
    mpDialogImpl->m_aPopupMenuHdl = rLink;
}

void Dialog::SetInstallLOKNotifierHdl(const Link<void*, vcl::ILibreOfficeKitNotifier*>& rLink)
{
    mpDialogImpl->m_aInstallLOKNotifierHdl = rLink;
}

void Dialog::SetLOKTunnelingState(bool bEnabled)
{
    mpDialogImpl->m_bLOKTunneling = bEnabled;
}

void Dialog::StateChanged( StateChangedType nType )
{
    bool bTunnelingEnabled = mpDialogImpl->m_bLOKTunneling;

    if (nType == StateChangedType::InitShow)
    {
        DoInitialLayout();

        const bool bKitActive = comphelper::LibreOfficeKit::isActive();
        if (bKitActive && bTunnelingEnabled)
        {
            std::vector<vcl::LOKPayloadItem> aItems;
            aItems.emplace_back("type""dialog");
            aItems.emplace_back("size", GetSizePixel().toString());
            aItems.emplace_back("unique_id", this->get_id().toUtf8());
            if (!GetText().isEmpty())
                aItems.emplace_back("title", GetText().toUtf8());

            if (const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
            {
                pNotifier->notifyWindow(GetLOKWindowId(), u"created"_ustr, aItems);
                pNotifier->notifyWindow(GetLOKWindowId(), u"created"_ustr, aItems);
            }
            else
            {
                vcl::ILibreOfficeKitNotifier* pViewShell = mpDialogImpl->m_aInstallLOKNotifierHdl.Call(nullptr);
                if (pViewShell)
                {
                    SetLOKNotifier(pViewShell);
                    pViewShell->notifyWindow(GetLOKWindowId(), u"created"_ustr, aItems);
                }
            }
        }

        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)
    {
        const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier();
        if (pNotifier && bTunnelingEnabled)
        {
            std::vector<vcl::LOKPayloadItem> aPayload;
            aPayload.emplace_back("title", GetText().toUtf8());
            pNotifier->notifyWindow(GetLOKWindowId(), u"title_changed"_ustr, aPayload);
        }
    }

    SystemWindow::StateChanged( nType );

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

    if (!mbModalMode && nType == StateChangedType::Visible)
    {
        const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier();
        if (pNotifier && bTunnelingEnabled)
        {
            std::vector<vcl::LOKPayloadItem> aPayload;
            aPayload.emplace_back("title", GetText().toUtf8());
            pNotifier->notifyWindow(GetLOKWindowId(), IsVisible()? u"show"_ustr: u"hide"_ustr, aPayload);
        }
    }
}

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;

    // If there's a cancel button with a custom handler, then always give it a chance to
    // handle Dialog::Close
    PushButton* pCustomCancelButton;
    PushButton* pCancelButton = dynamic_cast<PushButton*>(get_widget_for_response(RET_CANCEL));
    if (!mbInClose && pCancelButton && pCancelButton->GetClickHdl().IsSet())
        pCustomCancelButton = pCancelButton;
    else
        pCustomCancelButton = nullptr;

    mbInClose = true;

    if (pCustomCancelButton)
    {
        pCustomCancelButton->Click();
        if (xWindow->isDisposed())
            return true;
        mbInClose = false;
        return false;
    }

    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() || mpDialogImpl->maEndCtx.isSet())
    {
        EndDialog();
        mbInClose = false;
        return true;
    }
    else
    {
        mbInClose = false;
        return SystemWindow::Close();
    }
}

bool Dialog::ImplStartExecute(bool async)
{
    setDeferredProperties();

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

    ImplSVData* pSVData = ImplGetSVData();

    const bool bKitActive = comphelper::LibreOfficeKit::isActive();

    const bool bModal = GetType() != WindowType::MODELESSDIALOG;

    if (bModal)
    {
        if (bKitActive && !GetLOKNotifier())
        {
            if (auto pNotifier = mpDialogImpl->m_aInstallLOKNotifierHdl.Call(nullptr))
                SetLOKNotifier(pNotifier);
            else
            {
                // gh#5908 handle pasting disallowed clipboard contents on iOS
                // When another app owns the current clipboard contents, pasting
                // will display a "allow or disallow" dialog. If the disallow
                // option is selected, the data from the UIPasteboard will be
                // garbage and we will find ourselves here. Since calling
                // SetLOKNotifier() with a nullptr aborts in an assert(), fix
                // the crash by failing gracefully.

                // Also pNotifier may be nullptr when a dialog (e.g., "update
                // links?") is to be shown when loading a document.
                // Never crash in release builds (assume "cancel"), but allow
                // to see the not yet async / not properly set up dialogs in
                // debug builds.
                assert(!"A dialog without a notifier: make me async / properly set up");
                return false;
            }
        }
        if (!async && Application::IsUseSystemEventLoop())
        {
            // As long as Application::Yield deliberately calls std::abort when trying to
            // synchronously execute modal dialogs, better cancel them here for now as a hack:
            SAL_WARN(
                "vcl""cancel synchronous execution of modal dialog " << ImplGetDialogText(this));
            return false;
        }

        switch ( Application::GetDialogCancelMode() )
        {
        case DialogCancelMode::Off:
            break;
        case DialogCancelMode::Silent:
            if (bModal && GetLOKNotifier())
            {
                // check if there's already some dialog being ::Execute()d
                const bool bDialogExecuting = std::any_of(pSVData->mpWinData->mpExecuteDialogs.begin(),
                                                          pSVData->mpWinData->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.");
            }

            if (o3tl::IsRunningUnitTest())
            { // helps starbasic unit tests show their errors
                std::cerr << "Dialog \"" << ImplGetDialogText(this)
                          << "\" cancelled in silent mode\n";
            }

            SAL_INFO(
                "vcl",
                "Dialog \"" << ImplGetDialogText(this)
                    << "\" cancelled in silent mode");
            return false;

        case DialogCancelMode::LOKSilent:
            return false;

        default// default cannot happen
        case DialogCancelMode::Fatal:
            std::abort();
        }

#ifdef DBG_UTIL
        vcl::Window* pParent = GetParent();
        if ( pParent )
        {
            pParent = pParent->ImplGetFirstOverlapWindow();
            if (pParent)
            {
                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->mpWinData->mpExecuteDialogs.push_back(this);

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

    mbInExecute = true;
    // no real modality in LibreOfficeKit
    if (!bKitActive && bModal)
        SetModalInputMode(true);

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

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

    if (bModal)
        pSVData->maAppData.mnModalMode++;

    css::uno::Reference<css::frame::XGlobalEventBroadcaster> xEventBroadcaster(
        css::frame::theGlobalEventBroadcaster::get(xContext), css::uno::UNO_SET_THROW);
    css::document::DocumentEvent aObject;
    aObject.EventName = "DialogExecute";
    aObject.Supplement <<= GetText(); // title
    xEventBroadcaster->documentEventOccured(aObject);
    if (bModal)
        UITestLogger::getInstance().log(Concat2View("Open Modal " + get_id()));
    else
        UITestLogger::getInstance().log(Concat2View("Open Modeless " + get_id()));

    bool bTunnelingEnabled = mpDialogImpl->m_bLOKTunneling;
    if (comphelper::LibreOfficeKit::isActive() && bTunnelingEnabled)
    {
        if (const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier())
        {
            // Dialog boxes don't get the Resize call and they
            // can have invalid size at 'created' message above.
            // If there is no difference, the client should detect it and ignore us,
            // otherwise, this should make sure that the window has the correct size.
            std::vector<vcl::LOKPayloadItem> aItems;
            aItems.emplace_back("size", GetSizePixel().toString());
            aItems.emplace_back("unique_id", this->get_id().toUtf8());
            pNotifier->notifyWindow(GetLOKWindowId(), u"size_changed"_ustr, aItems);
        }
    }

    return true;
}

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

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

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

    if ( !ImplStartExecute(false) )
        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::IsQuit() )
        Application::Yield();

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


    tools::Long nRet = mpDialogImpl->mnResult;
    mpDialogImpl->mnResult = -1;

    return static_cast<short>(nRet);
}

// virtual
bool Dialog::StartExecuteAsync( VclAbstractDialog::AsyncContext &rCtx )
{
    const bool bModal = GetType() != WindowType::MODELESSDIALOG;
    if (!ImplStartExecute(true))
    {
        rCtx.mxOwner.disposeAndClear();
        rCtx.mxOwnerDialogController.reset();
        rCtx.mxOwnerSelf.reset();
        return false;
    }

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

    return true;
}

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

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

void Dialog::EndDialog( tools::Long nResult )
{
    if (!mbInExecute || isDisposed())
        return;

    // do not let this object be destroyed from underneath us
    VclPtr<vcl::Window> xWindow = this;

    const bool bModal = GetType() != WindowType::MODELESSDIALOG;

    Hide();

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

    if (bModal)
    {
        SetModalInputMode(false);

        RemoveFromDlgList();

        // set focus to previous modal dialog if it is modal for
        // the same frame parent (or NULL)
        ImplSVData* pSVData = ImplGetSVData();
        if (!pSVData->mpWinData->mpExecuteDialogs.empty())
        {
            VclPtr<Dialog> pPrevious = pSVData->mpWinData->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();
            }
        }
    }

    mpDialogImpl->mnResult = nResult;

    if ( mpDialogImpl->mbStartedModal )
        ImplEndExecuteModal();

    if ( mpDialogImpl->maEndCtx.isSet() )
    {
        // We have a special case with async-dialogs that re-execute themselves.
        // In order to prevent overwriting state we need here, we need to extract
        // all the state we need before calling maEndDialogFn, because
        // maEndDialogFn might itself call StartExecuteAsync and store new state.
        std::shared_ptr<weld::DialogController> xOwnerDialogController = std::move(mpDialogImpl->maEndCtx.mxOwnerDialogController);
        std::shared_ptr<weld::Dialog> xOwnerSelf = std::move(mpDialogImpl->maEndCtx.mxOwnerSelf);
        auto xOwner = std::move(mpDialogImpl->maEndCtx.mxOwner);
        if ( mpDialogImpl->mbStartedModal )
        {
            mpDialogImpl->mbStartedModal = false;
            mpDialogImpl->mnResult = -1;
        }
        mbInExecute = false;
        auto fn = std::move(mpDialogImpl->maEndCtx.maEndDialogFn);

        // std::move leaves maEndDialogFn in a valid state with unspecified
        // value. For the SwSyncBtnDlg case gcc and msvc left maEndDialogFn
        // unset, but clang left maEndDialogFn at its original value, keeping
        // an extra reference to the DialogController in its lambda giving
        // an inconsistent lifecycle for the dialog. Force it to be unset.
        mpDialogImpl->maEndCtx.maEndDialogFn = nullptr;
        fn(nResult);

        // Destroy ourselves, if we have a context with VclPtr owner, and
        // we have not been re-executed.
        if (!mpDialogImpl->maEndCtx.isSet())
            xOwner.disposeAndClear();
        xOwnerDialogController.reset();
        xOwnerSelf.reset();
    }
    else
    {
        if ( mpDialogImpl->mbStartedModal )
        {
            mpDialogImpl->mbStartedModal = false;
            mpDialogImpl->mnResult = -1;
        }
        mbInExecute = false;
        // Destroy ourselves (if we have a context with VclPtr owner)
        std::shared_ptr<weld::DialogController> xOwnerDialogController = std::move(mpDialogImpl->maEndCtx.mxOwnerDialogController);
        std::shared_ptr<weld::Dialog> xOwnerSelf = std::move(mpDialogImpl->maEndCtx.mxOwnerSelf);
        mpDialogImpl->maEndCtx.mxOwner.disposeAndClear();
    }
}

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

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

    void EnableDialogInput(vcl::Window* pWindow)
    {
        if (Dialog* pDialog = dynamic_cast<Dialog*>(pWindow))
        {
            pDialog->EnableInput();
        }
    }

    void CloseTopLevel(vcl::Window* pWindow)
    {
        if (Dialog* pDialog = dynamic_cast<Dialog*>(pWindow))
            pDialog->Close();
        else if (FloatingWindow* pFloatWin = dynamic_cast<FloatingWindow*>(pWindow))
            pFloatWin->EndPopupMode(FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll);
    }
}

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

    ImplGetFrame()->SetModal(bModal);

    if (GetParent())
    {
        SalFrame* pFrame = GetParent()->ImplGetFrame();
        pFrame->NotifyModalHierarchy(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->mpWinData->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(thistrue))
            pPrevious->EnableInput(falsethis);

        // 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(thistrue))
        {
            pPrevious->EnableInput(truethis);

            // 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(thistrue))
            {
                pPrevious->ImplSetModalInputMode(false);
                pPrevious->ImplSetModalInputMode(true);
            }
        }
    }
}

vcl::Window* Dialog::GetFirstControlForFocus()
{
    vcl::Window* pFocusControl = nullptr;
    vcl::Window* pFirstOverlapWindow = ImplGetFirstOverlapWindow();

    // find focus control, even if the dialog has focus
    if (!HasFocus() && pFirstOverlapWindow && pFirstOverlapWindow->mpWindowImpl)
    {
        // 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 );
    }

    return pFocusControl;
}

void Dialog::GrabFocusToFirstControl()
{
    vcl::Window* pFocusControl = GetFirstControlForFocus();
    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, SystemTextColorFlags )
{
    Point aPos = pDev->LogicToPixel( rPos );
    Size aSize = GetSizePixel();

    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;

    bool bTunnelingEnabled = mpDialogImpl->m_bLOKTunneling;
    const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier();
    if (pNotifier && bTunnelingEnabled)
    {
        std::vector<vcl::LOKPayloadItem> aItems;
        aItems.emplace_back("size", GetSizePixel().toString());
        aItems.emplace_back("unique_id", this->get_id().toUtf8());
        pNotifier->notifyWindow(GetLOKWindowId(), u"size_changed"_ustr, aItems);
    }
}

bool Dialog::set_property(const OUString &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 || comphelper::LibreOfficeKit::isActive())
            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);

    if (mpActionArea)
    {
        //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 (const auto& a : aResponses)
    {
        if (a.second == response)
           return a.first;
    }

    return nullptr;
}

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

    if (mpActionArea)
    {
        //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 (const auto& a : aResponses)
    {
        if (a.first->GetStyle() & WB_DEFBUTTON)
        {
            return a.second;
        }
    }
    return RET_CANCEL;
}

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

    if (mpActionArea)
    {
        //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()
{
}

void VclBuilderContainer::setDeferredProperties()
{
    if (!m_pUIBuilder)
        return;
    m_pUIBuilder->setDeferredProperties();
}

VclBuilderContainer::~VclBuilderContainer()
{
}

void Dialog::Activate()
{
    if (GetType() == WindowType::MODELESSDIALOG)
    {
        const css::uno::Reference< css::uno::XComponentContext >& xContext(
                comphelper::getProcessComponentContext() );
        css::uno::Reference<css::frame::XGlobalEventBroadcaster> xEventBroadcaster(css::frame::theGlobalEventBroadcaster::get(xContext), css::uno::UNO_SET_THROW);
        css::document::DocumentEvent aObject;
        aObject.EventName = "ModelessDialogVisible";
        aObject.Supplement <<= GetText(); // title
        xEventBroadcaster->documentEventOccured(aObject);
    }
    SystemWindow::Activate();
}

void Dialog::Command(const CommandEvent& rCEvt)
{
    if (mpDialogImpl->m_aPopupMenuHdl.Call(rCEvt))
        return;
    SystemWindow::Command(rCEvt);
}

struct TopLevelWindowLockerImpl
{
    std::stack<std::vector<VclPtr<vcl::Window>>> m_aBusyStack;
};

TopLevelWindowLocker::TopLevelWindowLocker()
    : m_xImpl(std::make_unique<TopLevelWindowLockerImpl>())
{
}

void TopLevelWindowLocker::incBusy(const weld::Widget* pIgnore)
{
    // lock any toplevel windows from being closed until busy is over
    std::vector<VclPtr<vcl::Window>> aTopLevels;
    vcl::Window *pTopWin = Application::GetFirstTopLevelWindow();
    while (pTopWin)
    {
        vcl::Window* pCandidate = pTopWin;
        if (pCandidate->GetType() == WindowType::BORDERWINDOW)
            pCandidate = pCandidate->GetWindow(GetWindowType::FirstChild);
        // tdf#125266 ignore HelpTextWindows
        if (pCandidate &&
            pCandidate->GetType() != WindowType::HELPTEXTWINDOW &&
            pCandidate->GetType() != WindowType::FLOATINGWINDOW &&
            pCandidate->GetFrameWeld() != pIgnore)
        {
            aTopLevels.push_back(pCandidate);
        }
        pTopWin = Application::GetNextTopLevelWindow(pTopWin);
    }
    for (auto& a : aTopLevels)
    {
        a->IncModalCount();
        a->ImplGetFrame()->NotifyModalHierarchy(true);
    }
    m_xImpl->m_aBusyStack.push(aTopLevels);
}

void TopLevelWindowLocker::decBusy()
{
    // unlock locked toplevel windows from being closed now busy is over
    for (auto& a : m_xImpl->m_aBusyStack.top())
    {
        if (a->isDisposed())
            continue;
        a->DecModalCount();
        a->ImplGetFrame()->NotifyModalHierarchy(false);
    }
    m_xImpl->m_aBusyStack.pop();
}

bool TopLevelWindowLocker::isBusy() const
{
    return !m_xImpl->m_aBusyStack.empty();
}

TopLevelWindowLocker::~TopLevelWindowLocker()
{
}

void Dialog::DumpAsPropertyTree(tools::JsonWriter& rJsonWriter)
{
    SystemWindow::DumpAsPropertyTree(rJsonWriter);
    rJsonWriter.put("title", GetText());
    if (vcl::Window* pActionArea = get_action_area())
    {
        if (!pActionArea->IsVisible())
            rJsonWriter.put("collapsed"true);
    }

    OUString sDialogId = GetHelpId();
    sal_Int32 nStartPos = sDialogId.lastIndexOf('/');
    nStartPos = nStartPos >= 0 ? nStartPos + 1 : 0;
    rJsonWriter.put("dialogid", sDialogId.copy(nStartPos));

    {
        auto aResponses = rJsonWriter.startArray("responses");
        for (const auto& rResponse : mpDialogImpl->maResponses)
        {
            auto aResponse = rJsonWriter.startStruct();
            rJsonWriter.put("id", rResponse.first->get_id());
            rJsonWriter.put("response", rResponse.second);
        }
    }

    vcl::Window* pFocusControl = GetFirstControlForFocus();
    if (pFocusControl)
        rJsonWriter.put("init_focus_id", pFocusControl->get_id());
}

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

Messung V0.5
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.32 Sekunden  ¤

*© 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.