1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salplug.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
35 #include <tools/prex.h>
36 #include <X11/Xatom.h>
37 #include <tools/postx.h>
39 #include "vcl/dllapi.h"
41 #include "rtl/ustrbuf.hxx"
42 #include "osl/module.h"
43 #include "osl/process.h"
44 #include "osl/thread.h"
59 static const char * desktop_strings
[] = { "none", "unknown", "GNOME", "KDE", "KDE4", "CDE" };
61 static bool is_gnome_desktop( Display
* pDisplay
)
65 // warning: these checks are coincidental, GNOME does not
66 // explicitly advertise itself
68 if ( NULL
!= getenv( "GNOME_DESKTOP_SESSION_ID" ) )
73 Atom nAtom1
= XInternAtom( pDisplay
, "GNOME_SM_PROXY", True
);
74 Atom nAtom2
= XInternAtom( pDisplay
, "NAUTILUS_DESKTOP_WINDOW_ID", True
);
75 if( nAtom1
|| nAtom2
)
78 Atom
* pProperties
= XListProperties( pDisplay
, DefaultRootWindow( pDisplay
), &nProperties
);
79 if( pProperties
&& nProperties
)
81 for( int i
= 0; i
< nProperties
; i
++ )
82 if( pProperties
[ i
] == nAtom1
||
83 pProperties
[ i
] == nAtom2
)
94 Atom nUTFAtom
= XInternAtom( pDisplay
, "UTF8_STRING", True
);
95 Atom nNetWMNameAtom
= XInternAtom( pDisplay
, "_NET_WM_NAME", True
);
96 if( nUTFAtom
&& nNetWMNameAtom
)
98 // another, more expensive check: search for a gnome-panel
99 XLIB_Window aRoot
, aParent
, *pChildren
= NULL
;
100 unsigned int nChildren
= 0;
101 XQueryTree( pDisplay
, DefaultRootWindow( pDisplay
),
102 &aRoot
, &aParent
, &pChildren
, &nChildren
);
103 if( pChildren
&& nChildren
)
105 for( unsigned int i
= 0; i
< nChildren
&& ! ret
; i
++ )
109 unsigned long nItems
= 0, nBytes
= 0;
110 unsigned char* pProp
= NULL
;
111 XGetWindowProperty( pDisplay
,
122 if( pProp
&& nType
== nUTFAtom
)
124 OString
aWMName( (sal_Char
*)pProp
);
125 if( aWMName
.equalsIgnoreAsciiCase( "gnome-panel" ) )
139 static bool bWasXError
= false;
141 static inline bool WasXError()
143 bool bRet
= bWasXError
;
150 static int autodect_error_handler( Display
*, XErrorEvent
* )
156 typedef int(* XErrorHandler
)(Display
*,XErrorEvent
*);
159 static int KDEVersion( Display
* pDisplay
)
163 Atom nFullSession
= XInternAtom( pDisplay
, "KDE_FULL_SESSION", True
);
164 Atom nKDEVersion
= XInternAtom( pDisplay
, "KDE_SESSION_VERSION", True
);
171 Atom aRealType
= None
;
173 unsigned long nItems
= 0;
174 unsigned long nBytesLeft
= 0;
175 unsigned char* pProperty
= NULL
;
176 XGetWindowProperty( pDisplay
,
177 DefaultRootWindow( pDisplay
),
187 if( !WasXError() && nItems
!= 0 && pProperty
)
189 nRet
= *reinterpret_cast< sal_Int32
* >( pProperty
);
200 static bool is_kde_desktop( Display
* pDisplay
)
202 if ( NULL
!= getenv( "KDE_FULL_SESSION" ) )
204 const char *pVer
= getenv( "KDE_SESSION_VERSION" );
205 if ( !pVer
|| pVer
[0] == '0' )
207 return true; // does not exist => KDE3
210 rtl::OUString
aVer( RTL_CONSTASCII_USTRINGPARAM( "3" ) );
211 if ( aVer
.equalsIgnoreAsciiCaseAscii( pVer
) )
217 if ( KDEVersion( pDisplay
) == 3 )
223 static bool is_kde4_desktop( Display
* pDisplay
)
225 if ( NULL
!= getenv( "KDE_FULL_SESSION" ) )
227 rtl::OUString
aVer( RTL_CONSTASCII_USTRINGPARAM( "4" ) );
229 const char *pVer
= getenv( "KDE_SESSION_VERSION" );
230 if ( pVer
&& aVer
.equalsIgnoreAsciiCaseAscii( pVer
) )
234 if ( KDEVersion( pDisplay
) == 4 )
240 static bool is_cde_desktop( Display
* pDisplay
)
242 void* pLibrary
= NULL
;
244 Atom nDtAtom
= XInternAtom( pDisplay
, "_DT_WM_READY", True
);
245 OUString
aPathName( RTL_CONSTASCII_USTRINGPARAM( "file:///usr/dt/lib/libDtSvc.so" ) );
246 if( nDtAtom
&& ( pLibrary
= osl_loadModule( aPathName
.pData
, SAL_LOADMODULE_DEFAULT
) ) )
248 osl_unloadModule( (oslModule
)pLibrary
);
259 VCL_DLLPUBLIC
rtl::OUString
get_desktop_environment()
261 rtl::OUStringBuffer
aRet( 8 );
262 static const char *pOverride
= getenv( "OOO_FORCE_DESKTOP" );
264 if ( pOverride
&& *pOverride
)
266 OString
aOver( pOverride
);
268 if ( aOver
.equalsIgnoreAsciiCase( "cde" ) )
269 aRet
.appendAscii( desktop_strings
[DESKTOP_CDE
] );
270 if ( aOver
.equalsIgnoreAsciiCase( "kde4" ) )
271 aRet
.appendAscii( desktop_strings
[DESKTOP_KDE4
] );
272 if ( aOver
.equalsIgnoreAsciiCase( "gnome" ) )
273 aRet
.appendAscii( desktop_strings
[DESKTOP_GNOME
] );
274 if ( aOver
.equalsIgnoreAsciiCase( "kde" ) )
275 aRet
.appendAscii( desktop_strings
[DESKTOP_KDE
] );
276 if ( aOver
.equalsIgnoreAsciiCase( "none" ) )
277 aRet
.appendAscii( desktop_strings
[DESKTOP_UNKNOWN
] );
280 if( aRet
.getLength() == 0 )
282 // get display to connect to
283 const char* pDisplayStr
= getenv( "DISPLAY" );
284 int nParams
= osl_getCommandArgCount();
287 for( int i
= 0; i
< nParams
; i
++ )
289 osl_getCommandArg( i
, &aParam
.pData
);
290 if( aParam
.equalsAscii( "-headless" ) )
295 if( i
< nParams
-1 && (aParam
.equalsAscii( "-display" ) || aParam
.equalsAscii( "--display" )) )
297 osl_getCommandArg( i
+1, &aParam
.pData
);
298 aBParm
= OUStringToOString( aParam
, osl_getThreadTextEncoding() );
299 pDisplayStr
= aBParm
.getStr();
305 if( ! pDisplayStr
|| !*pDisplayStr
)
306 aRet
.appendAscii( desktop_strings
[DESKTOP_NONE
] );
309 /* #i92121# workaround deadlocks in the X11 implementation
311 static const char* pNoXInitThreads
= getenv( "SAL_NO_XINITTHREADS" );
313 from now on we know that an X connection will be
314 established, so protect X against itself
316 if( ! ( pNoXInitThreads
&& *pNoXInitThreads
) )
319 Display
* pDisplay
= XOpenDisplay( pDisplayStr
);
322 XErrorHandler pOldHdl
= XSetErrorHandler( autodect_error_handler
);
324 if ( is_kde4_desktop( pDisplay
) )
325 aRet
.appendAscii( desktop_strings
[DESKTOP_KDE4
] );
326 else if ( is_gnome_desktop( pDisplay
) )
327 aRet
.appendAscii( desktop_strings
[DESKTOP_GNOME
] );
328 else if ( is_cde_desktop( pDisplay
) )
329 aRet
.appendAscii( desktop_strings
[DESKTOP_CDE
] );
330 else if ( is_kde_desktop( pDisplay
) )
331 aRet
.appendAscii( desktop_strings
[DESKTOP_KDE
] );
333 aRet
.appendAscii( desktop_strings
[DESKTOP_UNKNOWN
] );
335 // set the default handler again
336 XSetErrorHandler( pOldHdl
);
338 XCloseDisplay( pDisplay
);
343 return aRet
.makeStringAndClear();