
/***************************************************************************
                          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() ), 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()
{
#if 0 /*def HAVE_XSCREENSAVER*/
	if ( !mitInfo_ ) mitInfo_ = XScreenSaverAllocInfo();
	XScreenSaverQueryInfo (qt_xdisplay(), DefaultRootWindow( qt_xdisplay() ), mitInfo_ );
  
	return mitInfo_->idle / 1000;
#else
  
	QWidgetList *list = QApplication::topLevelWidgets();
	QWidgetListIt it(*list);
	QWidget *w = it.current();
	delete list;
	if (w == NULL)
		return 0;
  
	// static XScreenSaverInfo *mit_info = NULL;
	if ( !mitInfo_ )
	{
		int event_base, error_base;
		if ( XScreenSaverQueryExtension( w->x11Display(), &event_base, &error_base ) )
		{
			mitInfo_ = XScreenSaverAllocInfo ();
		}
	}
	if ( !mitInfo_ )
	{
#ifdef NETDEBUG
		kdDebug() << "No XScreenSaver extension found on current XServer, disabling auto-away." << endl;
#endif
		timer_->stop();
		return 0;
	}
	if ( !XScreenSaverQueryInfo( w->x11Display(), qt_xrootwin(), mitInfo_ ) )
	{
#ifdef NETDEBUG
		kdDebug() << "XScreenSaverQueryInfo failed, disabling auto-away." << endl;
#endif
		timer_->stop();
		return 0;
	}
	return (mitInfo_->idle / 1000);
#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"
