
/***************************************************************************
                          xautolock.cpp  - user inactivity timer
                             -------------------
    begin                : Mon 01 Dec 2003
    copyright            : (C) 2002 by Michael Curtis
    email                : michael@kmess.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "xautolock.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xresource.h>
/* The following include is to make --enable-final work */
#include <X11/Xutil.h>

#ifdef HAVE_XSCREENSAVER
#include <X11/extensions/scrnsaver.h>
#endif

#include <qtimer.h>

#include <kdebug.h>

// Construct
XAutoLock::XAutoLock()
  : active_( false ),
    idle_( false ),
    idleTime_( 0 ),
    lastCheck_( time( 0 ) ),
    mitAvailable_( false ),
    mitInfo_( 0 ),
    triggerTime_( 0 )
{
  int dummy;

  timer_ = new QTimer( this, "idleCheckTimer" );
  timer_->stop();

  connect( timer_, SIGNAL( timeout()   ),
           this,     SLOT( checkIdle() ) );

  #ifdef HAVE_XSCREENSAVER
    mitAvailable_ = XScreenSaverQueryExtension(qt_xdisplay(), &dummy, &dummy) != 0;
  #endif
}


// Destroy
XAutoLock::~XAutoLock()
{
  emit activity();
  timer_->stop();
  delete timer_;
}


// The main function which checks for idle status
void XAutoLock::checkIdle()
{
  unsigned int now, timeIdle;

  now = time( 0 );

  if ( abs( lastCheck_ - now ) > 120 )
  {
    /*
      Whoah, two minutes since we were last called?  Something strange is happenning...
    */
    resetTimer();
  }

  lastCheck_ = now;

  if ( mitAvailable_ )
  {
    // ... then use that
    timeIdle = getMitIdle();
  }
  else
  {
    timeIdle = getMouseIdle();
  }

  if ( timeIdle > triggerTime_ && active_ )
  {
    emit timeout();
    idle_=true;
  }
  else
  {
    if ( idle_ ) resetTimer();
  }

}


// Get idle time by asking the MIT-SCREEN-SAVER extension (if available)
unsigned int XAutoLock::getMitIdle()
{
  #ifdef HAVE_XSCREENSAVER
    if ( !mitInfo_ ) mitInfo_ = XScreenSaverAllocInfo();
    XScreenSaverQueryInfo (qt_xdisplay(), DefaultRootWindow( qt_xdisplay() ), mitInfo_ );

    return mitInfo_->idle / 1000;
  #else
    return 0;
  #endif
}


// Get idle time by detecting time since last mouse movement
unsigned int XAutoLock::getMouseIdle()
{
  // NYI
  return 0;
}


// Reset the timer (after we've just become active again, for example)
void XAutoLock::resetTimer()
{
  idle_ = false;
  idleTime_ = time( 0 );

  emit activity();
}


// Set the timeout
void XAutoLock::setTimeOut( unsigned int timeOut )
{
  active_ = true;

  triggerTime_ = timeOut;
}


// Start the idle timer
void XAutoLock::startTimer()
{
  timer_->start( 5000 );

  resetTimer();
}


// Stop the idle timer
void XAutoLock::stopTimer()
{
  timer_->stop();
  active_ = false;
}


#include "xautolock.moc"
