Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <unx/svunx.h>
31 : : #include <unx/desktops.hxx>
32 : : #include <tools/prex.h>
33 : : #include <X11/Xatom.h>
34 : : #include <tools/postx.h>
35 : :
36 : : #include "rtl/process.h"
37 : : #include "rtl/ustrbuf.hxx"
38 : : #include "osl/module.h"
39 : : #include "osl/thread.h"
40 : : #include "vcl/svapp.hxx"
41 : :
42 : : #include "vclpluginapi.h"
43 : :
44 : : #include <unistd.h>
45 : : #include <string.h>
46 : :
47 : : using ::rtl::OUString;
48 : : using ::rtl::OString;
49 : :
50 : 0 : static bool is_gnome_desktop( Display* pDisplay )
51 : : {
52 : 0 : bool ret = false;
53 : :
54 : : // warning: these checks are coincidental, GNOME does not
55 : : // explicitly advertise itself
56 : :
57 [ # # ]: 0 : if ( NULL != getenv( "GNOME_DESKTOP_SESSION_ID" ) )
58 : 0 : ret = true;
59 : :
60 [ # # ]: 0 : if( ! ret )
61 : : {
62 : 0 : Atom nAtom1 = XInternAtom( pDisplay, "GNOME_SM_PROXY", True );
63 : 0 : Atom nAtom2 = XInternAtom( pDisplay, "NAUTILUS_DESKTOP_WINDOW_ID", True );
64 [ # # ][ # # ]: 0 : if( nAtom1 || nAtom2 )
65 : : {
66 : 0 : int nProperties = 0;
67 [ # # ]: 0 : Atom* pProperties = XListProperties( pDisplay, DefaultRootWindow( pDisplay ), &nProperties );
68 [ # # ][ # # ]: 0 : if( pProperties && nProperties )
69 : : {
70 [ # # ]: 0 : for( int i = 0; i < nProperties; i++ )
71 [ # # ][ # # ]: 0 : if( pProperties[ i ] == nAtom1 ||
72 : 0 : pProperties[ i ] == nAtom2 )
73 : : {
74 : 0 : ret = true;
75 : : }
76 [ # # ]: 0 : XFree( pProperties );
77 : : }
78 : : }
79 : : }
80 : :
81 [ # # ]: 0 : if( ! ret )
82 : : {
83 : 0 : Atom nUTFAtom = XInternAtom( pDisplay, "UTF8_STRING", True );
84 : 0 : Atom nNetWMNameAtom = XInternAtom( pDisplay, "_NET_WM_NAME", True );
85 [ # # ][ # # ]: 0 : if( nUTFAtom && nNetWMNameAtom )
86 : : {
87 : : // another, more expensive check: search for a gnome-panel
88 : 0 : XLIB_Window aRoot, aParent, *pChildren = NULL;
89 : 0 : unsigned int nChildren = 0;
90 : 0 : XQueryTree( pDisplay, DefaultRootWindow( pDisplay ),
91 [ # # ]: 0 : &aRoot, &aParent, &pChildren, &nChildren );
92 [ # # ][ # # ]: 0 : if( pChildren && nChildren )
93 : : {
94 [ # # ][ # # ]: 0 : for( unsigned int i = 0; i < nChildren && ! ret; i++ )
[ # # ]
95 : : {
96 : 0 : Atom nType = None;
97 : 0 : int nFormat = 0;
98 : 0 : unsigned long nItems = 0, nBytes = 0;
99 : 0 : unsigned char* pProp = NULL;
100 : : XGetWindowProperty( pDisplay,
101 : 0 : pChildren[i],
102 : : nNetWMNameAtom,
103 : : 0, 8,
104 : : False,
105 : : nUTFAtom,
106 : : &nType,
107 : : &nFormat,
108 : : &nItems,
109 : : &nBytes,
110 [ # # ]: 0 : &pProp );
111 [ # # ][ # # ]: 0 : if( pProp && nType == nUTFAtom )
112 : : {
113 : 0 : OString aWMName( (sal_Char*)pProp );
114 [ # # ]: 0 : if (
[ # # # # ]
115 : 0 : (aWMName.equalsIgnoreAsciiCase("gnome-shell")) ||
116 : 0 : (aWMName.equalsIgnoreAsciiCase("gnome-panel"))
117 : : )
118 : : {
119 : 0 : ret = true;
120 : 0 : }
121 : : }
122 [ # # ]: 0 : if( pProp )
123 [ # # ]: 0 : XFree( pProp );
124 : : }
125 [ # # ]: 0 : XFree( pChildren );
126 : : }
127 : : }
128 : : }
129 : :
130 : 0 : return ret;
131 : : }
132 : :
133 : : static bool bWasXError = false;
134 : :
135 : 0 : static inline bool WasXError()
136 : : {
137 : 0 : bool bRet = bWasXError;
138 : 0 : bWasXError = false;
139 : 0 : return bRet;
140 : : }
141 : :
142 : : extern "C"
143 : : {
144 : 0 : static int autodect_error_handler( Display*, XErrorEvent* )
145 : : {
146 : 0 : bWasXError = true;
147 : 0 : return 0;
148 : : }
149 : :
150 : : typedef int(* XErrorHandler)(Display*,XErrorEvent*);
151 : : }
152 : :
153 : 0 : static int TDEVersion( Display* pDisplay )
154 : : {
155 : 0 : int nRet = 0;
156 : :
157 : 0 : Atom nFullSession = XInternAtom( pDisplay, "TDE_FULL_SESSION", True );
158 : 0 : Atom nTDEVersion = XInternAtom( pDisplay, "TDE_SESSION_VERSION", True );
159 : :
160 [ # # ]: 0 : if( nFullSession )
161 : : {
162 [ # # ]: 0 : if( !nTDEVersion )
163 : 0 : return 14;
164 : :
165 : 0 : Atom aRealType = None;
166 : 0 : int nFormat = 8;
167 : 0 : unsigned long nItems = 0;
168 : 0 : unsigned long nBytesLeft = 0;
169 : 0 : unsigned char* pProperty = NULL;
170 : : XGetWindowProperty( pDisplay,
171 : 0 : DefaultRootWindow( pDisplay ),
172 : : nTDEVersion,
173 : : 0, 1,
174 : : False,
175 : : AnyPropertyType,
176 : : &aRealType,
177 : : &nFormat,
178 : : &nItems,
179 : : &nBytesLeft,
180 [ # # ]: 0 : &pProperty );
181 [ # # ][ # # ]: 0 : if( !WasXError() && nItems != 0 && pProperty )
[ # # ][ # # ]
182 : : {
183 : 0 : nRet = *reinterpret_cast< sal_Int32* >( pProperty );
184 : : }
185 [ # # ]: 0 : if( pProperty )
186 : : {
187 [ # # ]: 0 : XFree( pProperty );
188 : 0 : pProperty = NULL;
189 : : }
190 : : }
191 : 0 : return nRet;
192 : : }
193 : :
194 : 0 : static int KDEVersion( Display* pDisplay )
195 : : {
196 : 0 : int nRet = 0;
197 : :
198 : 0 : Atom nFullSession = XInternAtom( pDisplay, "KDE_FULL_SESSION", True );
199 : 0 : Atom nKDEVersion = XInternAtom( pDisplay, "KDE_SESSION_VERSION", True );
200 : :
201 [ # # ]: 0 : if( nFullSession )
202 : : {
203 [ # # ]: 0 : if( !nKDEVersion )
204 : 0 : return 3;
205 : :
206 : 0 : Atom aRealType = None;
207 : 0 : int nFormat = 8;
208 : 0 : unsigned long nItems = 0;
209 : 0 : unsigned long nBytesLeft = 0;
210 : 0 : unsigned char* pProperty = NULL;
211 : : XGetWindowProperty( pDisplay,
212 : 0 : DefaultRootWindow( pDisplay ),
213 : : nKDEVersion,
214 : : 0, 1,
215 : : False,
216 : : AnyPropertyType,
217 : : &aRealType,
218 : : &nFormat,
219 : : &nItems,
220 : : &nBytesLeft,
221 [ # # ]: 0 : &pProperty );
222 [ # # ][ # # ]: 0 : if( !WasXError() && nItems != 0 && pProperty )
[ # # ][ # # ]
223 : : {
224 : 0 : nRet = *reinterpret_cast< sal_Int32* >( pProperty );
225 : : }
226 [ # # ]: 0 : if( pProperty )
227 : : {
228 [ # # ]: 0 : XFree( pProperty );
229 : 0 : pProperty = NULL;
230 : : }
231 : : }
232 : 0 : return nRet;
233 : : }
234 : :
235 : 0 : static bool is_tde_desktop( Display* pDisplay )
236 : : {
237 [ # # ]: 0 : if ( NULL != getenv( "TDE_FULL_SESSION" ) )
238 : : {
239 : 0 : return true; // TDE
240 : : }
241 : :
242 [ # # ]: 0 : if ( TDEVersion( pDisplay ) >= 14 )
243 : 0 : return true;
244 : :
245 : 0 : return false;
246 : : }
247 : :
248 : 0 : static bool is_kde_desktop( Display* pDisplay )
249 : : {
250 [ # # ]: 0 : if ( NULL != getenv( "KDE_FULL_SESSION" ) )
251 : : {
252 : 0 : const char *pVer = getenv( "KDE_SESSION_VERSION" );
253 [ # # ][ # # ]: 0 : if ( !pVer || pVer[0] == '0' )
254 : : {
255 : 0 : return true; // does not exist => KDE3
256 : : }
257 : :
258 [ # # ]: 0 : rtl::OUString aVer( RTL_CONSTASCII_USTRINGPARAM( "3" ) );
259 [ # # ]: 0 : if ( aVer.equalsIgnoreAsciiCaseAscii( pVer ) )
260 : : {
261 : 0 : return true;
262 [ # # ]: 0 : }
263 : : }
264 : :
265 [ # # ]: 0 : if ( KDEVersion( pDisplay ) == 3 )
266 : 0 : return true;
267 : :
268 : 0 : return false;
269 : : }
270 : :
271 : 0 : static bool is_kde4_desktop( Display* pDisplay )
272 : : {
273 [ # # ]: 0 : if ( NULL != getenv( "KDE_FULL_SESSION" ) )
274 : : {
275 [ # # ]: 0 : rtl::OUString aVer( RTL_CONSTASCII_USTRINGPARAM( "4" ) );
276 : :
277 : 0 : const char *pVer = getenv( "KDE_SESSION_VERSION" );
278 [ # # ][ # # ]: 0 : if ( pVer && aVer.equalsIgnoreAsciiCaseAscii( pVer ) )
[ # # ]
279 [ # # ]: 0 : return true;
280 : : }
281 : :
282 [ # # ]: 0 : if ( KDEVersion( pDisplay ) == 4 )
283 : 0 : return true;
284 : :
285 : 0 : return false;
286 : : }
287 : :
288 : : extern "C"
289 : : {
290 : :
291 : 212 : DESKTOP_DETECTOR_PUBLIC DesktopType get_desktop_environment()
292 : : {
293 [ + - ][ + - ]: 212 : static const char *pOverride = getenv( "OOO_FORCE_DESKTOP" );
294 : :
295 [ - + ][ # # ]: 212 : if ( pOverride && *pOverride )
296 : : {
297 : 0 : OString aOver( pOverride );
298 : :
299 [ # # ]: 0 : if ( aOver.equalsIgnoreAsciiCase( "tde" ) )
300 : 0 : return DESKTOP_TDE;
301 [ # # ]: 0 : if ( aOver.equalsIgnoreAsciiCase( "kde4" ) )
302 : 0 : return DESKTOP_KDE4;
303 [ # # ]: 0 : if ( aOver.equalsIgnoreAsciiCase( "gnome" ) )
304 : 0 : return DESKTOP_GNOME;
305 [ # # ]: 0 : if ( aOver.equalsIgnoreAsciiCase( "kde" ) )
306 : 0 : return DESKTOP_KDE;
307 [ # # ]: 0 : if ( aOver.equalsIgnoreAsciiCase( "none" ) )
308 [ # # ]: 0 : return DESKTOP_UNKNOWN;
309 : : }
310 : :
311 : : // get display to connect to
312 : 212 : const char* pDisplayStr = getenv( "DISPLAY" );
313 : :
314 : 212 : const char* pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" );
315 : :
316 [ # # + - ]: 424 : if ((pUsePlugin && (strcmp(pUsePlugin, "svp") == 0))
[ + - ][ - + ]
317 : 212 : || Application::IsHeadlessModeRequested())
318 : 212 : pDisplayStr = NULL;
319 : : else
320 : : {
321 [ # # ]: 0 : int nParams = rtl_getAppCommandArgCount();
322 : 0 : OUString aParam;
323 : 0 : OString aBParm;
324 [ # # ]: 0 : for( int i = 0; i < nParams; i++ )
325 : : {
326 [ # # ]: 0 : rtl_getAppCommandArg( i, &aParam.pData );
327 [ # # ][ # # ]: 0 : if( i < nParams-1 && (aParam == "-display" || aParam == "--display" ) )
[ # # ][ # # ]
328 : : {
329 [ # # ]: 0 : osl_getCommandArg( i+1, &aParam.pData );
330 [ # # ][ # # ]: 0 : aBParm = OUStringToOString( aParam, osl_getThreadTextEncoding() );
331 : 0 : pDisplayStr = aBParm.getStr();
332 : 0 : break;
333 : : }
334 : 0 : }
335 : : }
336 : :
337 : : // no server at all
338 [ - + ][ # # ]: 212 : if( ! pDisplayStr || !*pDisplayStr )
339 : 212 : return DESKTOP_NONE;
340 : :
341 : : /* #i92121# workaround deadlocks in the X11 implementation
342 : : */
343 [ # # ][ # # ]: 0 : static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
344 : : /* #i90094#
345 : : from now on we know that an X connection will be
346 : : established, so protect X against itself
347 : : */
348 [ # # ][ # # ]: 0 : if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
349 : 0 : XInitThreads();
350 : :
351 : 0 : Display* pDisplay = XOpenDisplay( pDisplayStr );
352 [ # # ]: 0 : if( pDisplay == NULL )
353 : 0 : return DESKTOP_NONE;
354 : :
355 : : DesktopType ret;
356 : :
357 : 0 : XErrorHandler pOldHdl = XSetErrorHandler( autodect_error_handler );
358 : :
359 [ # # ]: 0 : if ( is_tde_desktop( pDisplay ) )
360 : 0 : ret = DESKTOP_TDE;
361 [ # # ]: 0 : else if ( is_kde4_desktop( pDisplay ) )
362 : 0 : ret = DESKTOP_KDE4;
363 [ # # ]: 0 : else if ( is_gnome_desktop( pDisplay ) )
364 : 0 : ret = DESKTOP_GNOME;
365 [ # # ]: 0 : else if ( is_kde_desktop( pDisplay ) )
366 : 0 : ret = DESKTOP_KDE;
367 : : else
368 : 0 : ret = DESKTOP_UNKNOWN;
369 : :
370 : : // set the default handler again
371 : 0 : XSetErrorHandler( pOldHdl );
372 : :
373 : 0 : XCloseDisplay( pDisplay );
374 : :
375 : 212 : return ret;
376 : : }
377 : :
378 : : }
379 : :
380 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|