LCOV - code coverage report
Current view: top level - vcl/unx/generic/desktopdetect - desktopdetector.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 16 189 8.5 %
Date: 2014-11-03 Functions: 3 11 27.3 %
Legend: Lines: hit not hit

          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 <prex.h>
      21             : #include <X11/Xatom.h>
      22             : #include <postx.h>
      23             : 
      24             : #include <unx/desktops.hxx>
      25             : 
      26             : #include "rtl/bootstrap.hxx"
      27             : #include "rtl/process.h"
      28             : #include "rtl/ustrbuf.hxx"
      29             : #include "osl/module.h"
      30             : #include "osl/thread.h"
      31             : #include "vcl/svapp.hxx"
      32             : 
      33             : #include "vclpluginapi.h"
      34             : 
      35             : #include <unistd.h>
      36             : #include <string.h>
      37             : 
      38           0 : static bool is_gnome_desktop( Display* pDisplay )
      39             : {
      40           0 :     bool ret = false;
      41             : 
      42             :     // warning: these checks are coincidental, GNOME does not
      43             :     // explicitly advertise itself
      44           0 :     if ( NULL != getenv( "GNOME_DESKTOP_SESSION_ID" ) )
      45           0 :         ret = true;
      46             : 
      47           0 :     if( ! ret )
      48             :     {
      49           0 :         Atom nAtom1 = XInternAtom( pDisplay, "GNOME_SM_PROXY", True );
      50           0 :         Atom nAtom2 = XInternAtom( pDisplay, "NAUTILUS_DESKTOP_WINDOW_ID", True );
      51           0 :         if( nAtom1 || nAtom2 )
      52             :         {
      53           0 :             int nProperties = 0;
      54           0 :             Atom* pProperties = XListProperties( pDisplay, DefaultRootWindow( pDisplay ), &nProperties );
      55           0 :             if( pProperties && nProperties )
      56             :             {
      57           0 :                 for( int i = 0; i < nProperties; i++ )
      58           0 :                     if( pProperties[ i ] == nAtom1 ||
      59           0 :                         pProperties[ i ] == nAtom2 )
      60             :                 {
      61           0 :                     ret = true;
      62             :                 }
      63           0 :                 XFree( pProperties );
      64             :             }
      65             :         }
      66             :     }
      67             : 
      68           0 :     if( ! ret )
      69             :     {
      70           0 :         Atom nUTFAtom       = XInternAtom( pDisplay, "UTF8_STRING", True );
      71           0 :         Atom nNetWMNameAtom = XInternAtom( pDisplay, "_NET_WM_NAME", True );
      72           0 :         if( nUTFAtom && nNetWMNameAtom )
      73             :         {
      74             :             // another, more expensive check: search for a gnome-panel
      75           0 :             ::Window aRoot, aParent, *pChildren = NULL;
      76           0 :             unsigned int nChildren = 0;
      77           0 :             XQueryTree( pDisplay, DefaultRootWindow( pDisplay ),
      78           0 :                         &aRoot, &aParent, &pChildren, &nChildren );
      79           0 :             if( pChildren && nChildren )
      80             :             {
      81           0 :                 for( unsigned int i = 0; i < nChildren && ! ret; i++ )
      82             :                 {
      83           0 :                     Atom nType = None;
      84           0 :                     int nFormat = 0;
      85           0 :                     unsigned long nItems = 0, nBytes = 0;
      86           0 :                     unsigned char* pProp = NULL;
      87             :                     XGetWindowProperty( pDisplay,
      88           0 :                                         pChildren[i],
      89             :                                         nNetWMNameAtom,
      90             :                                         0, 8,
      91             :                                         False,
      92             :                                         nUTFAtom,
      93             :                                         &nType,
      94             :                                         &nFormat,
      95             :                                         &nItems,
      96             :                                         &nBytes,
      97           0 :                                         &pProp );
      98           0 :                     if( pProp && nType == nUTFAtom )
      99             :                     {
     100           0 :                         OString aWMName( (sal_Char*)pProp );
     101           0 :                         if (
     102           0 :                             (aWMName.equalsIgnoreAsciiCase("gnome-shell")) ||
     103           0 :                             (aWMName.equalsIgnoreAsciiCase("gnome-panel"))
     104             :                            )
     105             :                         {
     106           0 :                             ret = true;
     107           0 :                         }
     108             :                     }
     109           0 :                     if( pProp )
     110           0 :                         XFree( pProp );
     111             :                 }
     112           0 :                 XFree( pChildren );
     113             :             }
     114             :         }
     115             :     }
     116             : 
     117           0 :     return ret;
     118             : }
     119             : 
     120             : static bool bWasXError = false;
     121             : 
     122           0 : static inline bool WasXError()
     123             : {
     124           0 :     bool bRet = bWasXError;
     125           0 :     bWasXError = false;
     126           0 :     return bRet;
     127             : }
     128             : 
     129             : extern "C"
     130             : {
     131           0 :     static int autodect_error_handler( Display*, XErrorEvent* )
     132             :     {
     133           0 :         bWasXError = true;
     134           0 :         return 0;
     135             :     }
     136             : 
     137             :     typedef int(* XErrorHandler)(Display*,XErrorEvent*);
     138             : }
     139             : 
     140           0 : static int TDEVersion( Display* pDisplay )
     141             : {
     142           0 :     int nRet = 0;
     143             : 
     144           0 :     Atom nFullSession = XInternAtom( pDisplay, "TDE_FULL_SESSION", True );
     145           0 :     Atom nTDEVersion  = XInternAtom( pDisplay, "TDE_SESSION_VERSION", True );
     146             : 
     147           0 :     if( nFullSession )
     148             :     {
     149           0 :         if( !nTDEVersion )
     150           0 :             return 14;
     151             : 
     152           0 :         Atom                aRealType   = None;
     153           0 :         int                 nFormat     = 8;
     154           0 :         unsigned long       nItems      = 0;
     155           0 :         unsigned long       nBytesLeft  = 0;
     156           0 :         unsigned char*  pProperty   = NULL;
     157             :         XGetWindowProperty( pDisplay,
     158           0 :                             DefaultRootWindow( pDisplay ),
     159             :                             nTDEVersion,
     160             :                             0, 1,
     161             :                             False,
     162             :                             AnyPropertyType,
     163             :                             &aRealType,
     164             :                             &nFormat,
     165             :                             &nItems,
     166             :                             &nBytesLeft,
     167           0 :                             &pProperty );
     168           0 :         if( !WasXError() && nItems != 0 && pProperty )
     169             :         {
     170           0 :             nRet = *reinterpret_cast< sal_Int32* >( pProperty );
     171             :         }
     172           0 :         if( pProperty )
     173             :         {
     174           0 :             XFree( pProperty );
     175           0 :             pProperty = NULL;
     176             :         }
     177             :     }
     178           0 :     return nRet;
     179             : }
     180             : 
     181           0 : static int KDEVersion( Display* pDisplay )
     182             : {
     183           0 :     int nRet = 0;
     184             : 
     185           0 :     Atom nFullSession = XInternAtom( pDisplay, "KDE_FULL_SESSION", True );
     186           0 :     Atom nKDEVersion  = XInternAtom( pDisplay, "KDE_SESSION_VERSION", True );
     187             : 
     188           0 :     if( nFullSession )
     189             :     {
     190           0 :         if( !nKDEVersion )
     191           0 :             return 3;
     192             : 
     193           0 :         Atom                aRealType   = None;
     194           0 :         int                 nFormat     = 8;
     195           0 :         unsigned long       nItems      = 0;
     196           0 :         unsigned long       nBytesLeft  = 0;
     197           0 :         unsigned char*  pProperty   = NULL;
     198             :         XGetWindowProperty( pDisplay,
     199           0 :                             DefaultRootWindow( pDisplay ),
     200             :                             nKDEVersion,
     201             :                             0, 1,
     202             :                             False,
     203             :                             AnyPropertyType,
     204             :                             &aRealType,
     205             :                             &nFormat,
     206             :                             &nItems,
     207             :                             &nBytesLeft,
     208           0 :                             &pProperty );
     209           0 :         if( !WasXError() && nItems != 0 && pProperty )
     210             :         {
     211           0 :             nRet = *reinterpret_cast< sal_Int32* >( pProperty );
     212             :         }
     213           0 :         if( pProperty )
     214             :         {
     215           0 :             XFree( pProperty );
     216           0 :             pProperty = NULL;
     217             :         }
     218             :     }
     219           0 :     return nRet;
     220             : }
     221             : 
     222           0 : static bool is_tde_desktop( Display* pDisplay )
     223             : {
     224           0 :     if ( NULL != getenv( "TDE_FULL_SESSION" ) )
     225             :     {
     226           0 :         return true; // TDE
     227             :     }
     228             : 
     229           0 :     if ( TDEVersion( pDisplay ) >= 14 )
     230           0 :         return true;
     231             : 
     232           0 :     return false;
     233             : }
     234             : 
     235           0 : static bool is_kde_desktop( Display* pDisplay )
     236             : {
     237           0 :     if ( NULL != getenv( "KDE_FULL_SESSION" ) )
     238             :     {
     239           0 :         const char *pVer = getenv( "KDE_SESSION_VERSION" );
     240           0 :         if ( !pVer || pVer[0] == '0' )
     241             :         {
     242           0 :             return true; // does not exist => KDE3
     243             :         }
     244             : 
     245           0 :         OUString aVer( "3" );
     246           0 :         if ( aVer.equalsIgnoreAsciiCaseAscii( pVer ) )
     247             :         {
     248           0 :             return true;
     249           0 :         }
     250             :     }
     251             : 
     252           0 :     if ( KDEVersion( pDisplay ) == 3 )
     253           0 :         return true;
     254             : 
     255           0 :     return false;
     256             : }
     257             : 
     258           0 : static bool is_kde4_desktop( Display* pDisplay )
     259             : {
     260           0 :     if ( NULL != getenv( "KDE_FULL_SESSION" ) )
     261             :     {
     262           0 :         OUString aVer( "4" );
     263             : 
     264           0 :         const char *pVer = getenv( "KDE_SESSION_VERSION" );
     265           0 :         if ( pVer && aVer.equalsIgnoreAsciiCaseAscii( pVer ) )
     266           0 :             return true;
     267             :     }
     268             : 
     269           0 :     if ( KDEVersion( pDisplay ) == 4 )
     270           0 :         return true;
     271             : 
     272           0 :     return false;
     273             : }
     274             : 
     275             : extern "C"
     276             : {
     277             : 
     278           8 : DESKTOP_DETECTOR_PUBLIC DesktopType get_desktop_environment()
     279             : {
     280           8 :     static const char *pOverride = getenv( "OOO_FORCE_DESKTOP" );
     281             : 
     282           8 :     if ( pOverride && *pOverride )
     283             :     {
     284           0 :         OString aOver( pOverride );
     285             : 
     286           0 :         if ( aOver.equalsIgnoreAsciiCase( "tde" ) )
     287           0 :             return DESKTOP_TDE;
     288           0 :         if ( aOver.equalsIgnoreAsciiCase( "kde4" ) )
     289           0 :             return DESKTOP_KDE4;
     290           0 :         if ( aOver.equalsIgnoreAsciiCase( "gnome" ) )
     291           0 :             return DESKTOP_GNOME;
     292           0 :         if ( aOver.equalsIgnoreAsciiCase( "unity" ) )
     293           0 :             return DESKTOP_UNITY;
     294           0 :         if ( aOver.equalsIgnoreAsciiCase( "xfce" ) )
     295           0 :             return DESKTOP_XFCE;
     296           0 :         if ( aOver.equalsIgnoreAsciiCase( "mate" ) )
     297           0 :             return DESKTOP_MATE;
     298           0 :         if ( aOver.equalsIgnoreAsciiCase( "kde" ) )
     299           0 :             return DESKTOP_KDE;
     300           0 :         if ( aOver.equalsIgnoreAsciiCase( "none" ) )
     301           0 :             return DESKTOP_UNKNOWN;
     302             :     }
     303             : 
     304             :     // get display to connect to
     305           8 :     const char* pDisplayStr = getenv( "DISPLAY" );
     306             : 
     307           8 :     OUString plugin;
     308           8 :     rtl::Bootstrap::get("SAL_USE_VCLPLUGIN", plugin);
     309             : 
     310           8 :     if (plugin == "svp" || Application::IsHeadlessModeRequested())
     311           0 :         pDisplayStr = NULL;
     312             :     else
     313             :     {
     314           8 :         int nParams = rtl_getAppCommandArgCount();
     315           8 :         OUString aParam;
     316          16 :         OString aBParm;
     317           8 :         for( int i = 0; i < nParams; i++ )
     318             :         {
     319           0 :             rtl_getAppCommandArg( i, &aParam.pData );
     320           0 :             if( i < nParams-1 && (aParam == "-display" || aParam == "--display" ) )
     321             :             {
     322           0 :                 rtl_getAppCommandArg( i+1, &aParam.pData );
     323           0 :                 aBParm = OUStringToOString( aParam, osl_getThreadTextEncoding() );
     324           0 :                 pDisplayStr = aBParm.getStr();
     325           0 :                 break;
     326             :             }
     327           8 :         }
     328             :     }
     329             : 
     330             :     // no server at all
     331           8 :     if( ! pDisplayStr || !*pDisplayStr )
     332           8 :         return DESKTOP_NONE;
     333             : 
     334             :     /* #i92121# workaround deadlocks in the X11 implementation
     335             :     */
     336           0 :     static const char* pNoXInitThreads = getenv( "SAL_NO_XINITTHREADS" );
     337             :     /* #i90094#
     338             :        from now on we know that an X connection will be
     339             :        established, so protect X against itself
     340             :     */
     341           0 :     if( ! ( pNoXInitThreads && *pNoXInitThreads ) )
     342           0 :         XInitThreads();
     343             : 
     344           0 :     Display* pDisplay = XOpenDisplay( pDisplayStr );
     345           0 :     if( pDisplay == NULL )
     346           0 :         return DESKTOP_NONE;
     347             : 
     348             :     DesktopType ret;
     349             : 
     350           0 :     XErrorHandler pOldHdl = XSetErrorHandler( autodect_error_handler );
     351             : 
     352             :     const char *pSession;
     353           0 :     OString aDesktopSession;
     354           0 :     if ( ( pSession = getenv( "DESKTOP_SESSION" ) ) )
     355           0 :         aDesktopSession = OString( pSession, strlen( pSession ) );
     356             : 
     357             :     const char *pDesktop;
     358           0 :     OString aCurrentDesktop;
     359           0 :     if ( ( pDesktop = getenv( "XDG_CURRENT_DESKTOP" ) ) )
     360           0 :         aCurrentDesktop = OString( pDesktop, strlen( pDesktop ) );
     361             : 
     362             :     // fast environment variable checks
     363           0 :     if ( aCurrentDesktop.equalsIgnoreAsciiCase( "unity" ) )
     364           0 :         ret = DESKTOP_UNITY;
     365           0 :     else if ( aDesktopSession.equalsIgnoreAsciiCase( "gnome" ) )
     366           0 :         ret = DESKTOP_GNOME;
     367           0 :     else if ( aDesktopSession.equalsIgnoreAsciiCase( "mate" ) )
     368           0 :         ret = DESKTOP_MATE;
     369           0 :     else if ( aDesktopSession.equalsIgnoreAsciiCase( "xfce" ) )
     370           0 :         ret = DESKTOP_XFCE;
     371             : 
     372             :     // these guys can be slower, with X property fetches,
     373             :     // round-trips etc. and so are done later.
     374           0 :     else if ( is_kde4_desktop( pDisplay ) )
     375           0 :         ret = DESKTOP_KDE4;
     376           0 :     else if ( is_gnome_desktop( pDisplay ) )
     377           0 :         ret = DESKTOP_GNOME;
     378           0 :     else if ( is_kde_desktop( pDisplay ) )
     379           0 :         ret = DESKTOP_KDE;
     380           0 :     else if ( is_tde_desktop( pDisplay ) )
     381           0 :         ret = DESKTOP_TDE;
     382             :     else
     383           0 :         ret = DESKTOP_UNKNOWN;
     384             : 
     385             :     // set the default handler again
     386           0 :     XSetErrorHandler( pOldHdl );
     387             : 
     388           0 :     XCloseDisplay( pDisplay );
     389             : 
     390           8 :     return ret;
     391             : }
     392             : 
     393          24 : }
     394             : 
     395             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10