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

Generated by: LCOV version 1.11