blob: ec1bc044bfb5a877f16dcdf4c298601805980992 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_vcl.hxx"
#include "osl/module.h"
#include "osl/process.h"
#include "rtl/ustrbuf.hxx"
#include "salinst.hxx"
#include "unx/saldata.hxx"
#include "vcl/printerinfomanager.hxx"
#include <cstdio>
#include <unistd.h>
using namespace rtl;
extern "C" {
typedef SalInstance*(*salFactoryProc)( oslModule pModule);
}
static oslModule pCloseModule = NULL;
enum {
DESKTOP_NONE = 0,
DESKTOP_UNKNOWN,
DESKTOP_GNOME,
DESKTOP_KDE,
DESKTOP_KDE4,
DESKTOP_CDE
};
static const char * desktop_strings[] = { "none", "unknown", "GNOME", "KDE", "KDE4", "CDE" };
static SalInstance* tryInstance( const OUString& rModuleBase )
{
SalInstance* pInst = NULL;
OUStringBuffer aModName( 128 );
aModName.appendAscii( SAL_DLLPREFIX"vclplug_" );
aModName.append( rModuleBase );
aModName.appendAscii( SAL_DLLPOSTFIX );
aModName.appendAscii( SAL_DLLEXTENSION );
OUString aModule = aModName.makeStringAndClear();
oslModule aMod = osl_loadModuleRelative(
reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
SAL_LOADMODULE_DEFAULT );
if( aMod )
{
salFactoryProc aProc = (salFactoryProc)osl_getAsciiFunctionSymbol( aMod, "create_SalInstance" );
if( aProc )
{
pInst = aProc( aMod );
#if OSL_DEBUG_LEVEL > 1
std::fprintf( stderr, "sal plugin %s produced instance %p\n",
OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr(),
pInst );
#endif
if( pInst )
{
pCloseModule = aMod;
/*
* 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( rModuleBase.equalsAscii("gtk") )
{
pCloseModule = NULL;
}
/*
* #i109007# KDE3 seems to have the same problem; an atexit cleanup
* handler, which cannot be resolved anymore if the plugin is already unloaded.
*/
else if( rModuleBase.equalsAscii("kde") )
{
pCloseModule = NULL;
}
GetSalData()->m_pPlugin = aMod;
}
else
osl_unloadModule( aMod );
}
else
{
#if OSL_DEBUG_LEVEL > 1
std::fprintf( stderr, "could not load symbol %s from shared object %s\n",
"create_SalInstance",
OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif
osl_unloadModule( aMod );
}
}
#if OSL_DEBUG_LEVEL > 1
else
std::fprintf( stderr, "could not load shared object %s\n",
OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif
return pInst;
}
static const rtl::OUString& get_desktop_environment()
{
static rtl::OUString aRet;
if( ! aRet.getLength() )
{
OUStringBuffer aModName( 128 );
aModName.appendAscii( SAL_DLLPREFIX"desktop_detector" );
aModName.appendAscii( SAL_DLLPOSTFIX );
aModName.appendAscii( SAL_DLLEXTENSION );
OUString aModule = aModName.makeStringAndClear();
oslModule aMod = osl_loadModuleRelative(
reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
SAL_LOADMODULE_DEFAULT );
if( aMod )
{
rtl::OUString (*pSym)() = (rtl::OUString(*)())
osl_getAsciiFunctionSymbol( aMod, "get_desktop_environment" );
if( pSym )
aRet = pSym();
}
osl_unloadModule( aMod );
}
return aRet;
}
static SalInstance* autodetect_plugin()
{
static const char* pKDEFallbackList[] =
{
"kde4", "kde", "gtk", "gen", 0
};
static const char* pStandardFallbackList[] =
{
"gtk", "gen", 0
};
static const char* pHeadlessFallbackList[] =
{
"svp", 0
};
const rtl::OUString& desktop( get_desktop_environment() );
const char ** pList = pStandardFallbackList;
int nListEntry = 0;
// no server at all: dummy plugin
if ( desktop.equalsAscii( desktop_strings[DESKTOP_NONE] ) )
pList = pHeadlessFallbackList;
else if ( desktop.equalsAscii( desktop_strings[DESKTOP_GNOME] ) )
pList = pStandardFallbackList;
else if( desktop.equalsAscii( desktop_strings[DESKTOP_KDE] ) )
{
pList = pKDEFallbackList;
nListEntry = 1;
}
else if( desktop.equalsAscii( desktop_strings[DESKTOP_KDE4] ) )
pList = pKDEFallbackList;
SalInstance* pInst = NULL;
while( pList[nListEntry] && pInst == NULL )
{
rtl::OUString aTry( rtl::OUString::createFromAscii( pList[nListEntry] ) );
pInst = tryInstance( aTry );
#if OSL_DEBUG_LEVEL > 1
if( pInst )
std::fprintf( stderr, "plugin autodetection: %s\n", pList[nListEntry] );
#endif
nListEntry++;
}
return pInst;
}
static SalInstance* check_headless_plugin()
{
int nParams = osl_getCommandArgCount();
OUString aParam;
for( int i = 0; i < nParams; i++ )
{
osl_getCommandArg( i, &aParam.pData );
if( aParam.equalsAscii( "-headless" ) )
return tryInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "svp" ) ) );
}
return NULL;
}
SalInstance *CreateSalInstance()
{
SalInstance* pInst = NULL;
static const char* pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" );
if( !(pUsePlugin && *pUsePlugin) )
pInst = check_headless_plugin();
else
pInst = tryInstance( OUString::createFromAscii( pUsePlugin ) );
if( ! pInst )
pInst = autodetect_plugin();
// fallback to gen
if( ! pInst )
pInst = tryInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "gen" ) ) );
if( ! pInst )
{
std::fprintf( stderr, "no suitable windowing system found, exiting.\n" );
_exit( 1 );
}
// acquire SolarMutex
pInst->AcquireYieldMutex( 1 );
return pInst;
}
void DestroySalInstance( SalInstance *pInst )
{
// release SolarMutex
pInst->ReleaseYieldMutex();
delete pInst;
if( pCloseModule )
osl_unloadModule( pCloseModule );
}
void InitSalData()
{
}
void DeInitSalData()
{
}
void InitSalMain()
{
}
void DeInitSalMain()
{
}
void SalAbort( const XubString& rErrorText )
{
if( !rErrorText.Len() )
std::fprintf( stderr, "Application Error" );
else
std::fprintf( stderr, ByteString( rErrorText, gsl_getSystemTextEncoding() ).GetBuffer() );
abort();
}
const OUString& SalGetDesktopEnvironment()
{
return get_desktop_environment();
}
SalData::SalData() :
m_pInstance(NULL),
m_pPlugin(NULL),
m_pPIManager(NULL)
{
}
SalData::~SalData()
{
psp::PrinterInfoManager::release();
}