File indexing completed on 2024-04-28 05:32:09

0001 /*
0002     this file is part of the oxygen gtk engine
0003     SPDX-FileCopyrightText: 2010 Hugo Pereira Da Costa <hugo.pereira@free.fr>
0004 
0005     inspired notably from kdelibs/kdeui/color/kcolorutils.h
0006     SPDX-FileCopyrightText: 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
0007     SPDX-FileCopyrightText: 2007 Thomas Zander <zander@kde.org>
0008     SPDX-FileCopyrightText: 2007 Zack Rusin <zack@kde.org>
0009 
0010     SPDX-License-Identifier: LGPL-2.0-or-later
0011 */
0012 
0013 #include "oxygenapplicationname.h"
0014 #include "oxygengtkutils.h"
0015 #include "oxygenxulapplicationnames.h"
0016 #include "config.h"
0017 
0018 #include <cstdlib>
0019 #include <fstream>
0020 #include <iostream>
0021 #include <sstream>
0022 #include <unistd.h>
0023 
0024 namespace Oxygen
0025 {
0026 
0027     //__________________________________________________________________________
0028     void ApplicationName::initialize( void )
0029     {
0030 
0031         // get application name from gtk
0032         std::string gtkAppName( fromGtk() );
0033 
0034         // get application name from pid
0035         std::string pidAppName( fromPid( getpid() ) );
0036 
0037         #if OXYGEN_DEBUG
0038         std::cerr << "ApplicationName::initialize -"
0039             << " from pid: " << pidAppName
0040             << " from gtk: " << gtkAppName
0041             << std::endl;
0042         #endif
0043 
0044         // initialize to unknown
0045         _name = Unknown;
0046 
0047         // Way to override appname detection
0048         const char* envAppName(getenv("OXYGEN_APPLICATION_NAME_OVERRIDE"));
0049         if(envAppName)
0050         {
0051             gtkAppName=envAppName;
0052             pidAppName=envAppName;
0053         }
0054 
0055         if( pidAppName == "opera" ) _name = Opera;
0056         else if( gtkAppName == "eclipse" || gtkAppName == "Eclipse" ) _name = Eclipse;
0057         else if( pidAppName == "java" ) {
0058 
0059             if( !( gtkAppName.empty() || gtkAppName == "<unknown>" ) ) _name = JavaSwt;
0060             else _name = Java;
0061 
0062         } else if( gtkAppName == "acroread" ) _name = Acrobat;
0063         else if( gtkAppName == "soffice" ) _name = OpenOffice;
0064         else if( gtkAppName == "gimp" ) _name = Gimp;
0065         else if(
0066             gtkAppName == "chrome" ||
0067             gtkAppName == "chromium" ||
0068             gtkAppName == "chromium-browser" ||
0069             gtkAppName == "google-chrome" ) _name = GoogleChrome;
0070 
0071         else {
0072 
0073             for( unsigned int index = 0; !XulAppNames[index].empty(); ++index )
0074             {
0075                 if( gtkAppName.find( XulAppNames[index] ) == 0 || pidAppName.find( XulAppNames[index] ) == 0 )
0076                 {
0077                     _name = XUL;
0078                     break;
0079                 }
0080             }
0081         }
0082 
0083         // For now, only LibreOffice passes its version, so for other apps version will remain NULL
0084         _version=getenv("LIBO_VERSION");
0085 
0086         #if OXYGEN_DEBUG
0087         std::cerr << "ApplicationName::initialize -"
0088             << " from pid: " << pidAppName
0089             << " from gtk: " << gtkAppName
0090             << " internal: " << *this
0091             << " version: " << (_version?_version:"0x0")
0092             << std::endl;
0093         #endif
0094 
0095 
0096     }
0097 
0098     //__________________________________________________________________________
0099     bool ApplicationName::isGtkDialogWidget( GtkWidget* widget ) const
0100     {
0101         GtkWidget* parent( gtk_widget_get_toplevel( widget ) );
0102 
0103         // check parent
0104         return parent && GTK_IS_DIALOG( parent );
0105     }
0106 
0107     //__________________________________________________________________________
0108     bool ApplicationName::useFlatBackground( GtkWidget* widget ) const
0109     {
0110 
0111         // check application name
0112         if( !(
0113             isXul() ||
0114             isAcrobat() ||
0115             isJavaSwt() ||
0116             isGoogleChrome() ||
0117             isEclipse() ) ) return false;
0118 
0119         // check for Gtk dialog type
0120         if( widget && isGtkDialogWidget( widget ) ) return false;
0121 
0122         // return true in all other cases
0123         return true;
0124 
0125     }
0126 
0127     //__________________________________________________________________________
0128     std::string ApplicationName::fromGtk( void ) const
0129     {
0130         if( const char* gtkAppName = g_get_prgname() ) return gtkAppName;
0131         else return "";
0132     }
0133 
0134     //__________________________________________________________________________
0135     std::string ApplicationName::fromPid( int pid ) const
0136     {
0137 
0138         // generate /proc filename
0139         std::ostringstream filename;
0140         filename << "/proc/" << pid << "/cmdline";
0141 
0142         // try read file
0143         std::ifstream in( filename.str().c_str() );
0144         if( !in ) return std::string();
0145         std::string line;
0146         std::getline( in, line, '\0' );
0147         const size_t pos( line.rfind( '/' ) );
0148         return ( pos == std::string::npos ) ? line:line.substr( pos+1 );
0149 
0150 //         /*
0151 //         somehow std::getline gets some extra crap (non char) from the procfile
0152 //         one has to use ifstream::getline, and pass it a fixed size line
0153 //         */
0154 //         char lineC[1024];
0155 //         in.getline( lineC, 1024, '\n' );
0156 //         std::string line( lineC );
0157 //
0158 //         // get position of last "/" character, and truncate accordingly
0159 //         const size_t pos = line.rfind( '/' );
0160 //         if( pos == std::string::npos ) return line;
0161 //         else return line.substr( pos+1 );
0162 
0163     }
0164 
0165     //__________________________________________________________________________
0166     std::ostream& operator << ( std::ostream& out, const ApplicationName& app )
0167     {
0168         switch( app._name )
0169         {
0170             default:
0171             case Unknown: out << "Unknown"; break;
0172             case Acrobat: out << "Acrobat"; break;
0173             case XUL: out << "XUL (Mozilla)"; break;
0174             case Gimp: out << "Gimp"; break;
0175             case OpenOffice: out << "OpenOffice"; break;
0176             case GoogleChrome: out << "GoogleChrome"; break;
0177             case Opera: out << "Opera"; break;
0178             case Java: out << "Java"; break;
0179             case JavaSwt: out << "JavaSwt"; break;
0180             case Eclipse: out << "Eclipse"; break;
0181         }
0182 
0183         return out;
0184     }
0185 }