Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  salplug.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 .
 */


// Th current high-level preprocessor structure is:
//
// if !HAVE_FEATURE_UI
//   => STATIC_SAL_INSTANCE
// else
//   ? !STATIC_SAL_INSTANCE
//   ? UNIX_DESKTOP_DETECT
// endif
//
// ENABLE_HEADLESS just signifies the use of the SVP plugin!

#include <config_features.h>
#include <config_vclplug.h>

#include <cstdio>
#include <desktop/crashreport.hxx>
#include <rtl/bootstrap.hxx>
#include <rtl/process.h>
#include <salinst.hxx>
#include <sal/log.hxx>
#include <svdata.hxx>
#include <vcl/svapp.hxx>

#if HAVE_FEATURE_UI
#if USING_X11
#define UNIX_DESKTOP_DETECT 1
#include <unx/desktops.hxx>
#else
#define UNIX_DESKTOP_DETECT 0
#endif
#endif

#if defined(DISABLE_DYNLOADING) || !HAVE_FEATURE_UI
#define STATIC_SAL_INSTANCE 1
extern "C" SalInstance* create_SalInstance();
#else
#define STATIC_SAL_INSTANCE 0
#include <osl/module.hxx>
#endif

#if defined(iOS)
#include <premac.h>
#include <UIKit/UIKit.h>
#include <postmac.h>

#elif defined(ANDROID)
#include <android/androidinst.hxx>
#endif

#if defined(_WIN32)
#include <o3tl/char16_t2wchar_t.hxx>
#include <salframe.hxx>
#include <Windows.h>
#else
#include <unistd.h>
#endif

#if ENABLE_HEADLESS
#include <headless/svpdata.hxx>
#include <headless/svpinst.hxx>
#endif

namespace {

#if ENABLE_HEADLESS
SalInstance* svp_create_SalInstance()
{
    SvpSalInstance* pInstance = new SvpSalInstance(std::make_unique<SvpSalYieldMutex>());
    new SvpSalData();
    return pInstance;
}
#endif

#if HAVE_FEATURE_UI

#if !STATIC_SAL_INSTANCE
oslModule pCloseModule = nullptr;

extern "C" typedef SalInstance* (*salFactoryProc)();

SalInstance* tryInstance( const OUString& rModuleBase, bool bForce = false )
{
#if ENABLE_HEADLESS
    if (rModuleBase == "svp")
        return svp_create_SalInstance();
#endif

    SalInstance* pInst = nullptr;
    OUString aUsedModuleBase(rModuleBase);
    if (aUsedModuleBase == "kde5")
        aUsedModuleBase = "kf5";
    OUString aModule(
#ifdef SAL_DLLPREFIX
            SAL_DLLPREFIX
#endif
            "vclplug_" + aUsedModuleBase + "lo" SAL_DLLEXTENSION );

    osl::Module aMod;
    if (aMod.loadRelative(reinterpret_cast<oslGenericFunction>(&tryInstance), aModule, SAL_LOADMODULE_GLOBAL))
    {
        salFactoryProc aProc = reinterpret_cast<salFactoryProc>(aMod.getFunctionSymbol("create_SalInstance"));
        if (aProc)
        {
            pInst = aProc();
            SAL_INFO(
                "vcl.plugadapt",
                "sal plugin " << aModule << " produced instance " << pInst);
            if (pInst)
            {
                pCloseModule = static_cast<oslModule>(aMod);
                aMod.release();

                /*
                 * Recent GTK+ versions load their modules with RTLD_LOCAL, so we can
                 * not access the 'gnome_accessibility_module_shutdown' anymore.
                 * So make sure libgtk+ & co are still mapped into memory when
                 * atk-bridge's atexit handler gets called.
                 */

                if (aUsedModuleBase == "gtk4" || aUsedModuleBase == "gtk3" ||
                    aUsedModuleBase == "gtk3_kde5" || aUsedModuleBase == "kf5" ||
                    aUsedModuleBase == "kf6" ||
                    aUsedModuleBase == "qt5" || aUsedModuleBase == "qt6" ||
                    aUsedModuleBase == "win")
                {
                    pCloseModule = nullptr;
                }
            }
        }
        else
        {
            SAL_WARN(
                "vcl.plugadapt",
                "could not load symbol create_SalInstance from shared object "
                    << aModule);
        }
    }
    else if (bForce)
    {
        SAL_WARN("vcl.plugadapt""could not load shared object " << aModule);
    }
    else
    {
        SAL_INFO("vcl.plugadapt""could not load shared object " << aModule);
    }

    // coverity[leaked_storage] - this is on purpose
    return pInst;
}
#endif // !STATIC_SAL_INSTANCE

#if UNIX_DESKTOP_DETECT

#if !STATIC_SAL_INSTANCE
const charconst* autodetect_plugin_list()
{
    static const charconst pKDEFallbackList[] =
    {
#if ENABLE_KF5
        "kf5",
#endif
#if ENABLE_GTK3_KDE5
        "gtk3_kde5",
#endif
#if ENABLE_GTK3
        "gtk3",
#endif
#if ENABLE_GEN
        "gen",
#endif
        nullptr
    };

    static const charconst pPlasma6FallbackList[] =
    {
#if ENABLE_KF6
        "kf6",
#endif
#if ENABLE_KF5
        "kf5",
#endif
#if ENABLE_GTK3_KDE5
        "gtk3_kde5",
#endif
#if ENABLE_GTK3
        "gtk3",
#endif
#if ENABLE_GEN
        "gen",
#endif
        nullptr
    };

    static const charconst pStandardFallbackList[] =
    {
#if ENABLE_GTK3
        "gtk3",
#endif
#if ENABLE_GEN
        "gen",
#endif
        nullptr
    };

#if ENABLE_HEADLESS
    static const charconst pHeadlessFallbackList[] =
    {
        "svp",
        nullptr
    };
#endif

    DesktopType desktop = get_desktop_environment();
    const char * const * pList = pStandardFallbackList;

#if ENABLE_HEADLESS
    // no server at all: dummy plugin
    if ( desktop == DESKTOP_NONE )
        pList = pHeadlessFallbackList;
    else
#endif
        if ( desktop == DESKTOP_GNOME ||
              desktop == DESKTOP_UNITY ||
              desktop == DESKTOP_XFCE  ||
              desktop == DESKTOP_MATE )
        pList = pStandardFallbackList;
    else if (desktop == DESKTOP_PLASMA5 || desktop == DESKTOP_LXQT)
        pList = pKDEFallbackList;
    else if (desktop == DESKTOP_PLASMA6)
        pList = pPlasma6FallbackList;

    return pList;
}
#endif // !STATIC_SAL_INSTANCE
#endif // UNIX_DESKTOP_DETECT

#endif // HAVE_FEATURE_UI

// HACK to obtain Application::IsHeadlessModeEnabled early on, before
// Application::EnableHeadlessMode has potentially been called:
bool IsHeadlessModeRequested()
{
    if (Application::IsHeadlessModeEnabled()) {
        return true;
    }
    sal_uInt32 n = rtl_getAppCommandArgCount();
    for (sal_uInt32 i = 0; i < n; ++i) {
        OUString arg;
        rtl_getAppCommandArg(i, &arg.pData);
        if ( arg == "--headless" || arg == "-headless" ) {
            return true;
        }
    }
    return false;
}

// anonymous namespace

SalInstance *CreateSalInstance()
{
    OUString aUsePlugin;
    rtl::Bootstrap::get(u"SAL_USE_VCLPLUGIN"_ustr, aUsePlugin);
    SAL_INFO_IF(!aUsePlugin.isEmpty(), "vcl.plugadapt""Requested VCL plugin: " << aUsePlugin);

    if (Application::IsBitmapRendering() || (aUsePlugin.isEmpty() && IsHeadlessModeRequested()))
        aUsePlugin = "svp";

    if (aUsePlugin == "svp")
    {
        Application::EnableBitmapRendering();
#if ENABLE_HEADLESS
        return svp_create_SalInstance();
#else
        aUsePlugin.clear();
#endif
    }

#if STATIC_SAL_INSTANCE
    return create_SalInstance();

#else // !STATIC_SAL_INSTANCE
    SalInstance *pInst = nullptr;

    if( !aUsePlugin.isEmpty() )
        pInst = tryInstance( aUsePlugin, true );

#if UNIX_DESKTOP_DETECT
    const charconst* pPluginList = pInst ? nullptr : autodetect_plugin_list();
    for (int i = 0; !pInst && pPluginList[i]; ++i)
    {
        pInst = tryInstance(OUString::createFromAscii(pPluginList[i]));
        SAL_INFO_IF(pInst, "vcl.plugadapt""plugin autodetection: " << pPluginList[i]);
    }
#endif

    // fallback, try everything
    static const charconst pPlugin[] = {
#ifdef _WIN32
        "win",
#elif defined(MACOSX)
        "osx",
#else // !_WIN32 && !MACOSX
#if ENABLE_GTK3
        "gtk3",
#endif
#if ENABLE_KF5
        "kf5",
#endif
#if ENABLE_GTK3_KDE5
        "gtk3_kde5",
#endif
#if ENABLE_GEN
        "gen",
#endif
#if ENABLE_QT5
        "qt5",
#endif
#if ENABLE_KF6
        "kf6",
#endif
#if ENABLE_QT6
        "qt6",
#endif
#endif // !_WIN32 && !MACOSX
        nullptr
    };

    for (int i = 0; !pInst && pPlugin[i]; ++i)
        pInst = tryInstance( OUString::createFromAscii( pPlugin[ i ] ) );

    if( ! pInst )
    {
        std::fprintf( stderr, "no suitable windowing system found, exiting.\n" );
        _exit( 1 );
    }

    return pInst;
#endif // !STATIC_SAL_INSTANCE
}

void DestroySalInstance( SalInstance *pInst )
{
    delete pInst;
#if !STATIC_SAL_INSTANCE
    if( pCloseModule )
        osl_unloadModule( pCloseModule );
#endif
}

void SalAbort( const OUString& rErrorText, bool bDumpCore )
{
    if (GetSalInstance())
        GetSalInstance()->BeforeAbort(rErrorText, bDumpCore);

#if defined _WIN32
    if( rErrorText.isEmpty() )
    {
        // make sure crash reporter is triggered
        RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, nullptr );
        FatalAppExitW( 0, L"Application Error" );
    }
    else
    {
        CrashReporter::addKeyValue("AbortMessage", rErrorText, CrashReporter::Write);
        // make sure crash reporter is triggered
        RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, nullptr );
        FatalAppExitW( 0, o3tl::toW(rErrorText.getStr()) );
    }
#else // !_WIN32
#if defined ANDROID
    OUString aError(rErrorText.isEmpty() ? "Unspecified application error" : rErrorText);
    LOGE("SalAbort: '%s'", OUStringToOString(aError, osl_getThreadTextEncoding()).getStr());
#elif defined(iOS)
    NSLog(@"SalAbort: %s", OUStringToOString(rErrorText, osl_getThreadTextEncoding()).getStr());
#else
    if( rErrorText.isEmpty() )
        std::fprintf( stderr, "Unspecified Application Error\n" );
    else
    {
        CrashReporter::addKeyValue(u"AbortMessage"_ustr, rErrorText, CrashReporter::Write);
        std::fprintf( stderr, "%s\n", OUStringToOString(rErrorText, osl_getThreadTextEncoding()).getStr() );
    }
#endif
    if( bDumpCore )
        abort();
    else
        _exit(1);
#endif // !_WIN32
}

const OUString& SalGetDesktopEnvironment()
{
#if !HAVE_FEATURE_UI
    static OUString aDesktopEnvironment("headless");
#elif defined(_WIN32)
    static OUString aDesktopEnvironment( "Windows" );
#elif defined(MACOSX)
    static OUString aDesktopEnvironment( "MacOSX" );
#elif defined(EMSCRIPTEN)
    static OUString aDesktopEnvironment("WASM");
#elif defined(ANDROID)
    static OUString aDesktopEnvironment("android");
#elif defined(iOS)
    static OUString aDesktopEnvironment("iOS");
#elif UNIX_DESKTOP_DETECT
    // Order to match desktops.hxx' DesktopType
    static constexpr OUString desktop_strings[] = {
        u"none"_ustr, u"unknown"_ustr, u"GNOME"_ustr, u"UNITY"_ustr,
        u"XFCE"_ustr, u"MATE"_ustr, u"PLASMA5"_ustr, u"PLASMA6"_ustr, u"LXQT"_ustr };
    static OUString aDesktopEnvironment;
    if( aDesktopEnvironment.isEmpty())
    {
        aDesktopEnvironment = desktop_strings[get_desktop_environment()];
    }
#else
    static OUString aDesktopEnvironment("unknown");
#endif
    return aDesktopEnvironment;
}

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

Messung V0.5
C=91 H=97 G=93

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

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






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge