Logo Search packages:      
Sourcecode: qsynaptics version File versions  Download package

syntp.cpp

/***************************************************************************
 *   Copyright (C) 2004 by Stefan Kombrink                                 *
 *   katakombi@web.de                                                      *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
 
#include <stdlib.h>
#include <string>

#include <iostream>
#include <fstream>

#include "syntp.h"
#include "synparam.h"


//
// constructor
//
SynTouchPad::SynTouchPad()
{
    char keyStr[256];
    float val;
    
    // default setup of config file name
    cfgFN = std::string(getenv("HOME"));
     
    if (cfgFN.length())
        std::cout<<"users home is "<< cfgFN.c_str()<<std::endl;
    else 
    {
        std::cout<<"homedir not defined"<<std::endl;
        cfgFN="";
    }
    cfgFN.append("/.qsynaptics");
    
    
    // parse and store the actual settings
    if (hasSynaptics())
    {
        FILE *fs;
        fs = popen("synclient -l|grep '='|tr -d ' '|tr -s '=' '\n'","r");
        while (!feof(fs))
        {
            fscanf(fs,"%s",keyStr);
            fscanf(fs,"%f",&val);
            myDefaultConfig[keyStr] = val;
            myPrevConfig[keyStr]    = val;
            myConfig[keyStr]        = val;
            std::cout << keyStr << ":::" << val << std::endl;
        }
        pclose(fs);
    
    
        // read syndaemon timing
        myDefaultConfig[SYNDAEMONTIMING]=getSynDaemonTiming();
        myPrevConfig[SYNDAEMONTIMING]=myDefaultConfig[SYNDAEMONTIMING];
        myConfig[SYNDAEMONTIMING]=myDefaultConfig[SYNDAEMONTIMING];  
        
        // read syndaemon state
        if ( 0 == getSynDaemonTiming() ) 
        {
            myConfig[SYNDAEMONOFF]=1;
            myDefaultConfig[SYNDAEMONOFF]=1;
            myPrevConfig[SYNDAEMONOFF]=1;
        }
        else
        {
            myConfig[SYNDAEMONOFF]=0;
            myDefaultConfig[SYNDAEMONOFF]=0;
            myPrevConfig[SYNDAEMONOFF]=0;
            
            // the syndaemon might betray us, since TOUCHPADOFF==1 
            // when there was a key press lately.
            // If the syndaemon is running acually, the touchpad IS enabled!
            myConfig[TOUCHPADOFF]=0;
            myPrevConfig[TOUCHPADOFF]=0;
            myDefaultConfig[TOUCHPADOFF]=0;
        }
    }
    
    if (myConfig[MAXTAPTIME])
    {
        myConfig[TAPPINGOFF]=0;
        myPrevConfig[TAPPINGOFF]=0;
        myDefaultConfig[TAPPINGOFF]=0;
    }
    else
    {
        myConfig[TAPPINGOFF]=1;
        myPrevConfig[TAPPINGOFF]=1;
        myDefaultConfig[TAPPINGOFF]=1;
    }
    
    // we have to preset the mode for scrolling!
    if (myConfig[CIRCULARSCROLLING])
    {
        myConfig[SCROLLINGMODE]=2;
        myDefaultConfig[SCROLLINGMODE]=2;
        myPrevConfig[SCROLLINGMODE]=2;
    }
    else
    {
        myConfig[SCROLLINGMODE]=1;
        myDefaultConfig[SCROLLINGMODE]=1;
        myPrevConfig[SCROLLINGMODE]=1;
    }
}

//
// destructor
//
SynTouchPad::~SynTouchPad() 
{
}
 
//
// applies temporary changes to the hardware
//
bool SynTouchPad::apply(SynParam param)
{
   std::map<std::string,float>::iterator it;
   char cmdStr[255];
   int retVal = 0;
   
   // treat custom parameters
   if (param[SCROLLINGMODE]==0) 
   {
       param[VSCROLLEMUOFF]=1;
       param[HSCROLLEMUOFF]=1;
       param[CIRCULARSCROLLING]=0;
   }
   
   if (param[SCROLLINGMODE]==1)
   {
       param[VSCROLLEMUOFF]=0;
       param[HSCROLLEMUOFF]=0;
       param[CIRCULARSCROLLING]=0;       
   }
   
   if (param[SCROLLINGMODE]==2)
   {
       param[VSCROLLEMUOFF]=1;
       param[HSCROLLEMUOFF]=1;
       param[CIRCULARSCROLLING]=1;       
   }
      
   
   if (param[VSCROLLEMUOFF]==1) param[VERTSCROLLDELTA]=0;
   if (param[HSCROLLEMUOFF]==1) param[HORIZSCROLLDELTA]=0;
       
   
   if (param[TAPPINGOFF]==1) param[MAXTAPTIME]=0;
   
   for (it = param.begin(); it != param.end(); it++)
   {
       std::pair<std::string,float> p = *it;

       // only monitor REAL changes!
       if (p.second != myPrevConfig[p.first])
       {
           
           std::cout << "New " << p.first << " is " << p.second << std::endl;
           myPrevConfig[p.first] = p.second;

           // skip the loop if there is a custom parameter
           if (isCustomParameter(p.first))
               continue;
           
           snprintf(cmdStr,255,"synclient %s=%g",p.first.c_str(),p.second);
           retVal+=system(cmdStr);
       }
   }
    
   if ((param[TOUCHPADOFF]==1) | (param[SYNDAEMONOFF]==1))
       applySynDaemonTiming(0);
   else
       applySynDaemonTiming(param[SYNDAEMONTIMING]);
       
   if (param[TOUCHPADOFF]==1) disableTP(); else enableTP();
     
   std::cout<<"retVal is "<<retVal<<std::endl;

   return (!(bool)retVal);
}

//
// applies the changes the user made
//
bool SynTouchPad::applyConfig()
{
    std::cout << "activate changes..." << std::endl;
   
    // since the user applied, store the new settings onto HD
    return apply(myConfig);
}

//
// applies and stores the changes
//
bool SynTouchPad::applyAndStoreConfig()
{
    std::cout << "activate AND save changes..." << std::endl;
   
    // since the user applied, store the new settings onto HD
    storeConfig(myConfig);
    return apply(myConfig);
}

//
// restore the settings the user had in the beginning
//
bool SynTouchPad::cancelConfig()
{
    std::cout << "restore old settings..." << std::endl;
    return apply(myDefaultConfig);
}


//
// checks on synaptics driver installation
// FIXME checks on synclient, since /var/log/* isn't 
//     readable on every system and we need that tool anyways!
//     ...would be better to check on the module as well..
//
bool SynTouchPad::hasSynaptics()
{
    return !system("synclient -l > /dev/null");
}

//
// checks on syndaemon
//
bool SynTouchPad::hasSynDaemon()
{
    FILE *sdck;
    sdck=popen("whereis syndaemon|cut -d ':' -f2|tr -d ' \n'","r");

    // read one char...
    getc(sdck);

    return ( !feof(sdck) && (pclose(sdck) != -1) );
}

//
// detects XFree86 version
// 
char *SynTouchPad::detectXFree86Version()
{
    static char verStr[255];
    FILE *xfck;

    xfck=popen("xdpyinfo|grep -i XFree86|grep -i Version|cut -d ':' -f2","r");

    fscanf(xfck,"%s",verStr); //FIXME! replace by fnscanf!
    if (strlen(verStr)==0) strncpy(verStr,"any",3);

    pclose(xfck);

    return &verStr[0];
}

//
// detect Synaptics Driver version
//
char *SynTouchPad::detectSynapticsVersion()
{
    static char verStr[255];
    FILE *stck;
    
    // does the synclient version support the -V parameter yet?
    if (system("synclient -V") == system("synclient -h"))
    {
        stck=popen("synclient -V","r");
    
        fscanf(stck,"%s",verStr); //FIXME replace by fnscanf
        
    
        pclose(stck);
    }
    else
        strncpy(verStr, "any below 0.13.3",16);
    
    return &verStr[0];
}

//
// checks on SHM configuration ability
//
bool SynTouchPad::hasSHMConfigurability() { return (system("synclient -h") != 1);}

//
// disables touch pad temporarily
// 
bool SynTouchPad::disableTP() 
{ 
    myConfig[TOUCHPADOFF] = 1;
    return system("synclient TouchPadOff=1"); 
}

//
// enable touch pad temporarily
// 
bool SynTouchPad::enableTP() 
{ 
    myConfig[TOUCHPADOFF] = 0;
    return system("synclient TouchPadOff=0"); 
}

//
// gets actual syndaemon timing
//
float SynTouchPad::getSynDaemonTiming()
{
    int runningInstances=0;
    FILE *sdck;
    float timing=2.0; // default!
    
    sdck=popen("ps ax|grep -v grep|grep -c syndaemon","r");
    fscanf(sdck,"%d",&runningInstances);
    pclose(sdck);
    
    if (!runningInstances) return 0.0;
    
    sdck=popen("ps ax|grep -v grep|grep syndaemon|sed 's/^.*syndaemon//g'|\
            sed 's/-i//g'", "r");

    fscanf(sdck,"%g",&timing);
    pclose(sdck);

    return timing;
}


//
// apply syndaemon timing
//
bool SynTouchPad::applySynDaemonTiming(float delay) 
{
    char execStr[255];
    if (!hasSynDaemon()) return FALSE;

    // kill all instances
    system("killall -9 syndaemon");
    
    if (delay==0) return TRUE;
    myPrevConfig[SYNDAEMONTIMING] = delay;
        
    snprintf(execStr,255,"syndaemon -i %g >/dev/null&",delay);
    std::cout << "we exec " << execStr << std::endl;
    system(execStr);
    
    return TRUE;
}


//
// gets the touch pads parameter setting
// 
float SynTouchPad::getParameter(std::string paramName)
{
   return myConfig[paramName];
}

//
// sets the touch pads parameters
// 
bool SynTouchPad::setParameter(std::string paramName, float param)
{   
    // if the entry exists, update the value and return 1 else return 0
    if (myConfig.find(paramName) == myConfig.end())
        return FALSE;
    else
        myConfig[paramName] = param;
        
    // user may apply now!
    if (!isEqual(myConfig,myPrevConfig)) emit settingsChanged();
    
    //std::cout <<  "setParameter"<<std::endl;
    return TRUE;
}


//
// checks whether two maps of parameters are different or not
//
bool SynTouchPad::isEqual(SynTouchPad::SynParam &a, SynTouchPad::SynParam &b)
{
    std::map<std::string,float>::iterator it;
    
    for (it=a.begin();it!=a.end();it++)
    {
        std::pair<std::string,float> p = *it;
        
        // exists the key/val pair?
        if (b.find(p.first)==b.end()) return FALSE;
        // is the value identical?
        if (b[p.first] != p.second) return FALSE;
    }
    
    //std::cout<<"EQUAL!!!"<<std::endl;
    
    return TRUE;
}

//
// checks whether a is subset of b
//
bool SynTouchPad::isSubset(SynTouchPad::SynParam &a, SynTouchPad::SynParam &b)
{
    std::map<std::string,float>::iterator it;
    
    for (it=a.begin();it!=a.end();it++)
    {
        std::pair<std::string,float> p = *it;
        
        // exists the key/val pair?
        if (b.find(p.first)!=b.end())
        {
            // is the value identical?
            if (b[p.first] != p.second) return FALSE;
        }
    }
    
    std::cout << "SUBSET!!!!"<<std::endl;
    
    return TRUE;
}


//
// restores system settings from file system directly to hardware
//
bool SynTouchPad::restoreConfig()
{
    int retVal=0;
    char paramName[256];
    float paramVal;
    
    std::ifstream cfgFile(cfgFN.c_str());
    
    if (!hasSynaptics()) return FALSE;
    
    while (!cfgFile.eof() && cfgFile.good())
    {
        cfgFile >> paramName;
        cfgFile >> paramVal;
        
        std::cout<<"read "<<paramName<<"="<<paramVal<<std::endl;
       
        myConfig[paramName]=paramVal;
    }
    
    // check on TouchPadOff and disable syndaemon if neccessary
    if (myConfig[TOUCHPADOFF]==1) 
        myConfig[SYNDAEMONOFF]=1;
        
    
    // SYNDAEMONTIMING is an exception since our detection cannot handle that!
    // we have to override that value by hand!
    if (myPrevConfig[SYNDAEMONTIMING]==0) myPrevConfig[SYNDAEMONTIMING]=myConfig[SYNDAEMONTIMING];
    
    // the user may now apply the changed settings, if there are any
    if (!isSubset(myConfig,myPrevConfig)) emit settingsChanged();
    
    // do not forget to set the timing!
    return cfgFile.good() && (!retVal);
}

//
// stores the actual system settings onto the file system
//
void SynTouchPad::storeConfig(SynTouchPad::SynParam &param)
{
    std::map<std::string,float>::iterator it;
    std::ofstream cfgFile(cfgFN.c_str());

    for (it = param.begin(); it != param.end(); it++)
    {
        std::pair<std::string,float> p = *it;
        cfgFile << p.first << " " << p.second << std::endl;
    }
    cfgFile.close();
}

//
// returns whether this is a custom parameter or not
//
bool SynTouchPad::isCustomParameter(std::string paramName)
{
    if (paramName==VSCROLLEMUOFF) return TRUE;
    if (paramName==HSCROLLEMUOFF) return TRUE;
    if (paramName==SYNDAEMONOFF) return TRUE;
    if (paramName==SYNDAEMONTIMING) return TRUE;
    if (paramName==TAPPINGOFF) return TRUE;
    if (paramName==SCROLLINGMODE) return TRUE;
    
    return FALSE;
}

Generated by  Doxygen 1.6.0   Back to index