Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "osl/module.h"
21 : #include "osl/process.h"
22 :
23 : #include "rtl/ustrbuf.hxx"
24 :
25 : #include "salinst.hxx"
26 : #include "generic/gensys.h"
27 : #include "generic/gendata.hxx"
28 : #include "unx/desktops.hxx"
29 : #include "vcl/printerinfomanager.hxx"
30 :
31 : #include <cstdio>
32 : #include <unistd.h>
33 :
34 : using ::rtl::OUString;
35 : using ::rtl::OUStringBuffer;
36 : extern "C" {
37 : typedef SalInstance*(*salFactoryProc)( oslModule pModule);
38 : }
39 :
40 : static oslModule pCloseModule = NULL;
41 :
42 32 : static SalInstance* tryInstance( const OUString& rModuleBase, bool bForce = false )
43 : {
44 32 : SalInstance* pInst = NULL;
45 : // Disable gtk3 plugin for now unless explicitly requested via
46 : // SAL_USE_VCLPLUGIN=gtk3 (would ideally depend on experimental mode, but
47 : // reading the experimental mode setting requires the UNO service manager
48 : // which has not yet been instantiated):
49 32 : if (!bForce && rModuleBase.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("gtk3")))
50 : {
51 0 : return NULL;
52 : }
53 32 : OUStringBuffer aModName( 128 );
54 32 : aModName.appendAscii( SAL_DLLPREFIX"vclplug_" );
55 32 : aModName.append( rModuleBase );
56 32 : aModName.appendAscii( SAL_DLLPOSTFIX );
57 : // aModName.appendAscii( SAL_DLLEXTENSION );
58 32 : OUString aModule = aModName.makeStringAndClear();
59 :
60 : oslModule aMod = osl_loadModuleRelative(
61 : reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
62 32 : SAL_LOADMODULE_DEFAULT );
63 32 : if( aMod )
64 : {
65 32 : salFactoryProc aProc = (salFactoryProc)osl_getAsciiFunctionSymbol( aMod, "create_SalInstance" );
66 32 : if( aProc )
67 : {
68 32 : pInst = aProc( aMod );
69 : #if OSL_DEBUG_LEVEL > 1
70 : std::fprintf( stderr, "sal plugin %s produced instance %p\n",
71 : OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr(),
72 : pInst );
73 : #endif
74 32 : if( pInst )
75 : {
76 32 : pCloseModule = aMod;
77 :
78 : #ifndef ANDROID
79 : /*
80 : * Recent GTK+ versions load their modules with RTLD_LOCAL, so we can
81 : * not access the 'gnome_accessibility_module_shutdown' anymore.
82 : * So make sure libgtk+ & co are still mapped into memory when
83 : * atk-bridge's atexit handler gets called.
84 : * #i109007# KDE3 seems to have the same problem.
85 : * And same applies for KDE4.
86 : */
87 32 : if( rModuleBase == "gtk" || rModuleBase == "gtk3" || rModuleBase == "tde" || rModuleBase == "kde" || rModuleBase == "kde4" )
88 : {
89 0 : pCloseModule = NULL;
90 : }
91 : #endif
92 32 : GetSalData()->m_pPlugin = aMod;
93 : }
94 : else
95 0 : osl_unloadModule( aMod );
96 : }
97 : else
98 : {
99 : #if OSL_DEBUG_LEVEL > 1
100 : std::fprintf( stderr, "could not load symbol %s from shared object %s\n",
101 : "create_SalInstance",
102 : OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
103 : #endif
104 0 : osl_unloadModule( aMod );
105 : }
106 : }
107 : #if OSL_DEBUG_LEVEL > 1
108 : else
109 : std::fprintf( stderr, "could not load shared object %s\n",
110 : OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
111 : #endif
112 :
113 32 : return pInst;
114 : }
115 :
116 : #if !defined(ANDROID)
117 :
118 10 : static DesktopType get_desktop_environment()
119 : {
120 10 : OUStringBuffer aModName( 128 );
121 10 : aModName.appendAscii( SAL_DLLPREFIX"desktop_detector" );
122 10 : aModName.appendAscii( SAL_DLLPOSTFIX );
123 10 : OUString aModule = aModName.makeStringAndClear();
124 :
125 : oslModule aMod = osl_loadModuleRelative(
126 : reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
127 10 : SAL_LOADMODULE_DEFAULT );
128 10 : DesktopType ret = DESKTOP_UNKNOWN;
129 10 : if( aMod )
130 : {
131 : DesktopType (*pSym)() = (DesktopType(*)())
132 10 : osl_getAsciiFunctionSymbol( aMod, "get_desktop_environment" );
133 10 : if( pSym )
134 10 : ret = pSym();
135 : }
136 10 : osl_unloadModule( aMod );
137 10 : return ret;
138 : }
139 :
140 : #else
141 :
142 : #define get_desktop_environment() DESKTOP_NONE // For now...
143 :
144 : #endif
145 :
146 0 : static SalInstance* autodetect_plugin()
147 : {
148 : static const char* pTDEFallbackList[] =
149 : {
150 : "tde", "kde4", "kde", "gtk3", "gtk", "gen", 0
151 : };
152 :
153 : static const char* pKDEFallbackList[] =
154 : {
155 : "kde4", "kde", "gtk3", "gtk", "gen", 0
156 : };
157 :
158 : static const char* pStandardFallbackList[] =
159 : {
160 : "gtk3", "gtk", "gen", 0
161 : };
162 :
163 : static const char* pHeadlessFallbackList[] =
164 : {
165 : "svp", 0
166 : };
167 :
168 0 : DesktopType desktop = get_desktop_environment();
169 0 : const char ** pList = pStandardFallbackList;
170 0 : int nListEntry = 0;
171 :
172 : // no server at all: dummy plugin
173 0 : if ( desktop == DESKTOP_NONE )
174 0 : pList = pHeadlessFallbackList;
175 0 : else if ( desktop == DESKTOP_GNOME )
176 0 : pList = pStandardFallbackList;
177 0 : else if( desktop == DESKTOP_TDE )
178 0 : pList = pTDEFallbackList;
179 0 : else if( desktop == DESKTOP_KDE )
180 : {
181 0 : pList = pKDEFallbackList;
182 0 : nListEntry = 1;
183 : }
184 0 : else if( desktop == DESKTOP_KDE4 )
185 0 : pList = pKDEFallbackList;
186 :
187 0 : SalInstance* pInst = NULL;
188 0 : while( pList[nListEntry] && pInst == NULL )
189 : {
190 0 : rtl::OUString aTry( rtl::OUString::createFromAscii( pList[nListEntry] ) );
191 0 : pInst = tryInstance( aTry );
192 : #if OSL_DEBUG_LEVEL > 1
193 : if( pInst )
194 : std::fprintf( stderr, "plugin autodetection: %s\n", pList[nListEntry] );
195 : #endif
196 0 : nListEntry++;
197 0 : }
198 :
199 0 : return pInst;
200 : }
201 :
202 32 : static SalInstance* check_headless_plugin()
203 : {
204 32 : int nParams = osl_getCommandArgCount();
205 32 : OUString aParam;
206 64 : for( int i = 0; i < nParams; i++ )
207 : {
208 64 : osl_getCommandArg( i, &aParam.pData );
209 64 : if( aParam == "-headless" || aParam == "--headless" )
210 : {
211 32 : return tryInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "svp" ) ) );
212 : }
213 : }
214 0 : return NULL;
215 : }
216 :
217 32 : SalInstance *CreateSalInstance()
218 : {
219 32 : SalInstance* pInst = NULL;
220 :
221 32 : static const char* pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" );
222 :
223 32 : pInst = check_headless_plugin();
224 :
225 32 : if( !pInst && pUsePlugin && *pUsePlugin )
226 0 : pInst = tryInstance( OUString::createFromAscii( pUsePlugin ), true );
227 :
228 32 : if( ! pInst )
229 0 : pInst = autodetect_plugin();
230 :
231 : // fallback, try everything
232 32 : const char* pPlugin[] = { "gtk3", "gtk", "kde4", "kde", "tde", "gen", 0 };
233 :
234 32 : for ( int i = 0; !pInst && pPlugin[ i ]; ++i )
235 0 : pInst = tryInstance( OUString::createFromAscii( pPlugin[ i ] ) );
236 :
237 32 : if( ! pInst )
238 : {
239 0 : std::fprintf( stderr, "no suitable windowing system found, exiting.\n" );
240 0 : _exit( 1 );
241 : }
242 :
243 : // acquire SolarMutex
244 32 : pInst->AcquireYieldMutex( 1 );
245 :
246 32 : return pInst;
247 : }
248 :
249 0 : void DestroySalInstance( SalInstance *pInst )
250 : {
251 : // release SolarMutex
252 0 : pInst->ReleaseYieldMutex();
253 :
254 0 : delete pInst;
255 0 : if( pCloseModule )
256 0 : osl_unloadModule( pCloseModule );
257 0 : }
258 :
259 32 : void InitSalData()
260 : {
261 32 : }
262 :
263 0 : void DeInitSalData()
264 : {
265 0 : }
266 :
267 32 : void InitSalMain()
268 : {
269 32 : }
270 :
271 0 : void DeInitSalMain()
272 : {
273 0 : }
274 :
275 0 : void SalAbort( const rtl::OUString& rErrorText, bool bDumpCore )
276 : {
277 0 : if( rErrorText.isEmpty() )
278 0 : std::fprintf( stderr, "Application Error\n" );
279 : else
280 0 : std::fprintf( stderr, "%s\n", rtl::OUStringToOString(rErrorText, osl_getThreadTextEncoding()).getStr() );
281 0 : if( bDumpCore )
282 0 : abort();
283 : else
284 0 : _exit(1);
285 : }
286 :
287 : static const char * desktop_strings[] = { "none", "unknown", "GNOME", "TDE", "KDE", "KDE4" };
288 :
289 10 : const OUString& SalGetDesktopEnvironment()
290 : {
291 10 : static rtl::OUString aRet;
292 10 : if( aRet.isEmpty())
293 : {
294 10 : rtl::OUStringBuffer buf( 8 );
295 10 : buf.appendAscii( desktop_strings[ get_desktop_environment() ] );
296 10 : aRet = buf.makeStringAndClear();
297 : }
298 10 : return aRet;
299 : }
300 :
301 32 : SalData::SalData() :
302 : m_pInstance(NULL),
303 : m_pPlugin(NULL),
304 32 : m_pPIManager(NULL)
305 : {
306 32 : }
307 :
308 0 : SalData::~SalData()
309 : {
310 0 : psp::PrinterInfoManager::release();
311 0 : }
312 :
313 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|