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 : #include "rtl/bootstrap.hxx"
25 :
26 : #include "salinst.hxx"
27 : #include "generic/gensys.h"
28 : #include "generic/gendata.hxx"
29 : #include "unx/desktops.hxx"
30 : #include "vcl/printerinfomanager.hxx"
31 : #include <config_vclplug.h>
32 :
33 : #include <cstdio>
34 : #include <unistd.h>
35 :
36 : extern "C" {
37 : typedef SalInstance*(*salFactoryProc)( oslModule pModule);
38 : }
39 :
40 : static oslModule pCloseModule = NULL;
41 :
42 151 : static SalInstance* tryInstance( const OUString& rModuleBase, bool bForce = false )
43 : {
44 151 : 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 151 : if (!bForce && rModuleBase == "gtk3")
50 : {
51 0 : return NULL;
52 : }
53 151 : OUStringBuffer aModName( 128 );
54 151 : aModName.appendAscii( SAL_DLLPREFIX"vclplug_" );
55 151 : aModName.append( rModuleBase );
56 151 : aModName.appendAscii( SAL_DLLPOSTFIX );
57 302 : OUString aModule = aModName.makeStringAndClear();
58 :
59 : oslModule aMod = osl_loadModuleRelative(
60 : reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
61 151 : SAL_LOADMODULE_DEFAULT );
62 151 : if( aMod )
63 : {
64 151 : salFactoryProc aProc = (salFactoryProc)osl_getAsciiFunctionSymbol( aMod, "create_SalInstance" );
65 151 : if( aProc )
66 : {
67 151 : pInst = aProc( aMod );
68 : #if OSL_DEBUG_LEVEL > 1
69 : std::fprintf( stderr, "sal plugin %s produced instance %p\n",
70 : OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr(),
71 : pInst );
72 : #endif
73 151 : if( pInst )
74 : {
75 151 : pCloseModule = aMod;
76 :
77 : #ifndef ANDROID
78 : /*
79 : * Recent GTK+ versions load their modules with RTLD_LOCAL, so we can
80 : * not access the 'gnome_accessibility_module_shutdown' anymore.
81 : * So make sure libgtk+ & co are still mapped into memory when
82 : * atk-bridge's atexit handler gets called.
83 : * #i109007# KDE3 seems to have the same problem.
84 : * And same applies for KDE4.
85 : */
86 151 : if( rModuleBase == "gtk" || rModuleBase == "gtk3" || rModuleBase == "tde" || rModuleBase == "kde" || rModuleBase == "kde4" )
87 : {
88 0 : pCloseModule = NULL;
89 : }
90 : #endif
91 151 : GetSalData()->m_pPlugin = aMod;
92 : }
93 : else
94 0 : osl_unloadModule( aMod );
95 : }
96 : else
97 : {
98 : #if OSL_DEBUG_LEVEL > 1
99 : std::fprintf( stderr, "could not load symbol %s from shared object %s\n",
100 : "create_SalInstance",
101 : OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
102 : #endif
103 0 : osl_unloadModule( aMod );
104 : }
105 : }
106 : #if OSL_DEBUG_LEVEL > 1
107 : else
108 : std::fprintf( stderr, "could not load shared object %s\n",
109 : OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
110 : #endif
111 :
112 302 : return pInst;
113 : }
114 :
115 : #if !defined(ANDROID)
116 :
117 115 : static DesktopType get_desktop_environment()
118 : {
119 115 : OUStringBuffer aModName( 128 );
120 : #ifdef LIBO_MERGELIBS
121 : aModName.appendAscii( SAL_DLLPREFIX"merged" );
122 : #else
123 115 : aModName.appendAscii( SAL_DLLPREFIX"desktop_detector" );
124 : #endif
125 115 : aModName.appendAscii( SAL_DLLPOSTFIX );
126 230 : OUString aModule = aModName.makeStringAndClear();
127 :
128 : oslModule aMod = osl_loadModuleRelative(
129 : reinterpret_cast< oslGenericFunction >( &tryInstance ), aModule.pData,
130 115 : SAL_LOADMODULE_DEFAULT );
131 115 : DesktopType ret = DESKTOP_UNKNOWN;
132 115 : if( aMod )
133 : {
134 : DesktopType (*pSym)() = (DesktopType(*)())
135 115 : osl_getAsciiFunctionSymbol( aMod, "get_desktop_environment" );
136 115 : if( pSym )
137 115 : ret = pSym();
138 : }
139 115 : osl_unloadModule( aMod );
140 230 : return ret;
141 : }
142 :
143 : #else
144 :
145 : #define get_desktop_environment() DESKTOP_NONE // For now...
146 :
147 : #endif
148 :
149 2 : static SalInstance* autodetect_plugin()
150 : {
151 : static const char* pTDEFallbackList[] =
152 : {
153 : "tde",
154 : #if ENABLE_KDE4
155 : "kde4",
156 : #endif
157 : #if ENABLE_KDE
158 : "kde",
159 : #endif
160 : "gtk3", "gtk", "gen", 0
161 : };
162 :
163 : static const char* pKDEFallbackList[] =
164 : {
165 : #if ENABLE_KDE4
166 : "kde4",
167 : #endif
168 : #if ENABLE_KDE
169 : "kde",
170 : #endif
171 : "gtk3", "gtk", "gen", 0
172 : };
173 :
174 : static const char* pStandardFallbackList[] =
175 : {
176 : "gtk3", "gtk", "gen", 0
177 : };
178 :
179 : static const char* pHeadlessFallbackList[] =
180 : {
181 : "svp", 0
182 : };
183 :
184 2 : DesktopType desktop = get_desktop_environment();
185 2 : const char ** pList = pStandardFallbackList;
186 2 : int nListEntry = 0;
187 :
188 : // no server at all: dummy plugin
189 2 : if ( desktop == DESKTOP_NONE )
190 2 : pList = pHeadlessFallbackList;
191 0 : else if ( desktop == DESKTOP_GNOME ||
192 0 : desktop == DESKTOP_XFCE ||
193 : desktop == DESKTOP_MATE )
194 0 : pList = pStandardFallbackList;
195 0 : else if( desktop == DESKTOP_TDE )
196 0 : pList = pTDEFallbackList;
197 0 : else if( desktop == DESKTOP_KDE )
198 : {
199 0 : pList = pKDEFallbackList;
200 0 : nListEntry = 1;
201 : }
202 0 : else if( desktop == DESKTOP_KDE4 )
203 0 : pList = pKDEFallbackList;
204 :
205 2 : SalInstance* pInst = NULL;
206 6 : while( pList[nListEntry] && pInst == NULL )
207 : {
208 2 : OUString aTry( OUString::createFromAscii( pList[nListEntry] ) );
209 2 : pInst = tryInstance( aTry );
210 : #if OSL_DEBUG_LEVEL > 1
211 : if( pInst )
212 : std::fprintf( stderr, "plugin autodetection: %s\n", pList[nListEntry] );
213 : #endif
214 2 : nListEntry++;
215 2 : }
216 :
217 2 : return pInst;
218 : }
219 :
220 151 : SalInstance *CreateSalInstance()
221 : {
222 151 : SalInstance *pInst = NULL;
223 :
224 151 : OUString aUsePlugin;
225 151 : static const char* pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" );
226 151 : if( pUsePlugin )
227 11 : aUsePlugin = OUString::createFromAscii( pUsePlugin );
228 : else
229 140 : rtl::Bootstrap::get( "SAL_USE_VCLPLUGIN", aUsePlugin );
230 :
231 151 : if( Application::IsHeadlessModeRequested() )
232 138 : aUsePlugin = "svp";
233 :
234 151 : if( !aUsePlugin.isEmpty() )
235 149 : pInst = tryInstance( aUsePlugin, true );
236 :
237 151 : if( ! pInst )
238 2 : pInst = autodetect_plugin();
239 :
240 : // fallback, try everything
241 151 : const char* pPlugin[] = { "gtk3", "gtk", "kde4", "kde", "tde", "gen", 0 };
242 :
243 151 : for ( int i = 0; !pInst && pPlugin[ i ]; ++i )
244 0 : pInst = tryInstance( OUString::createFromAscii( pPlugin[ i ] ) );
245 :
246 151 : if( ! pInst )
247 : {
248 0 : std::fprintf( stderr, "no suitable windowing system found, exiting.\n" );
249 0 : _exit( 1 );
250 : }
251 :
252 : // acquire SolarMutex
253 151 : pInst->AcquireYieldMutex( 1 );
254 :
255 151 : return pInst;
256 : }
257 :
258 94 : void DestroySalInstance( SalInstance *pInst )
259 : {
260 : // release SolarMutex
261 94 : pInst->ReleaseYieldMutex();
262 :
263 94 : delete pInst;
264 94 : if( pCloseModule )
265 94 : osl_unloadModule( pCloseModule );
266 94 : }
267 :
268 151 : void InitSalData()
269 : {
270 151 : }
271 :
272 94 : void DeInitSalData()
273 : {
274 94 : }
275 :
276 151 : void InitSalMain()
277 : {
278 151 : }
279 :
280 0 : void SalAbort( const OUString& rErrorText, bool bDumpCore )
281 : {
282 0 : if( rErrorText.isEmpty() )
283 0 : std::fprintf( stderr, "Application Error\n" );
284 : else
285 0 : std::fprintf( stderr, "%s\n", OUStringToOString(rErrorText, osl_getThreadTextEncoding()).getStr() );
286 0 : if( bDumpCore )
287 0 : abort();
288 : else
289 0 : _exit(1);
290 : }
291 :
292 : // Order to match desktops.hxx' DesktopType
293 : static const char * desktop_strings[] = {
294 : "none", "unknown", "GNOME",
295 : "XFCE", "MATE", "TDE",
296 : "KDE", "KDE4" };
297 :
298 146 : const OUString& SalGetDesktopEnvironment()
299 : {
300 146 : static OUString aRet;
301 146 : if( aRet.isEmpty())
302 : {
303 113 : OUStringBuffer buf( 8 );
304 113 : buf.appendAscii( desktop_strings[ get_desktop_environment() ] );
305 113 : aRet = buf.makeStringAndClear();
306 : }
307 146 : return aRet;
308 : }
309 :
310 151 : SalData::SalData() :
311 : m_pInstance(NULL),
312 : m_pPlugin(NULL),
313 151 : m_pPIManager(NULL)
314 : {
315 151 : }
316 :
317 0 : SalData::~SalData()
318 : {
319 0 : psp::PrinterInfoManager::release();
320 465 : }
321 :
322 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|