|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// This file is part of the KDE project
|
|
|
|
//
|
|
|
|
// Copyright (c) 1999 Martin R. Jones <mjones@kde.org>
|
|
|
|
// Copyright (c) 2003 Lubos Lunak <l.lunak@kde.org>
|
|
|
|
//
|
|
|
|
// KDE screensaver engine
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "xautolock.h"
|
|
|
|
#include "xautolock.moc"
|
|
|
|
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <ctime>
|
|
|
|
#include "xautolock_c.h"
|
|
|
|
|
|
|
|
#ifdef HAVE_DPMS
|
|
|
|
extern "C" {
|
|
|
|
#include <X11/Xmd.h>
|
|
|
|
#ifndef Bool
|
|
|
|
#define Bool BOOL
|
|
|
|
#endif
|
|
|
|
#include <X11/extensions/dpms.h>
|
|
|
|
|
|
|
|
#ifndef HAVE_DPMSINFO_PROTO
|
|
|
|
Status DPMSInfo ( Display *, CARD16 *, BOOL * );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int xautolock_useXidle = 0;
|
|
|
|
int xautolock_useMit = 0;
|
|
|
|
xautolock_corner_t xautolock_corners[ 4 ];
|
|
|
|
|
|
|
|
static XAutoLock* self = NULL;
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
static int catchFalseAlarms(Display *, XErrorEvent *)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
//
|
|
|
|
// Detect user inactivity.
|
|
|
|
// Named XAutoLock after the program that it is based on.
|
|
|
|
//
|
|
|
|
XAutoLock::XAutoLock()
|
|
|
|
{
|
|
|
|
self = this;
|
|
|
|
xautolock_useXidle = 0;
|
|
|
|
xautolock_useMit = 0;
|
|
|
|
#ifdef HAVE_XIDLE
|
|
|
|
int dummy1;
|
|
|
|
xautolock_useXidle = XidleQueryExtension( tqt_xdisplay(), &dummy1, &dummy1 );
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_XSCREENSAVER
|
|
|
|
int dummy2;
|
|
|
|
if( !xautolock_useXidle )
|
|
|
|
xautolock_useMit = XScreenSaverQueryExtension( tqt_xdisplay(), &dummy2, &dummy2 );
|
|
|
|
#endif
|
|
|
|
if( !xautolock_useXidle && !xautolock_useMit )
|
|
|
|
{
|
|
|
|
kapp->installX11EventFilter( this );
|
|
|
|
int (*oldHandler)(Display *, XErrorEvent *);
|
|
|
|
oldHandler = XSetErrorHandler(catchFalseAlarms);
|
|
|
|
XSync(tqt_xdisplay(), False );
|
|
|
|
xautolock_initDiy( tqt_xdisplay());
|
|
|
|
XSync(tqt_xdisplay(), False );
|
|
|
|
XSetErrorHandler(oldHandler);
|
|
|
|
}
|
|
|
|
|
|
|
|
mTimeout = DEFAULT_TIMEOUT;
|
|
|
|
mDPMS = true;
|
|
|
|
resetTrigger();
|
|
|
|
|
|
|
|
time(&mLastTimeout);
|
|
|
|
mActive = false;
|
|
|
|
|
|
|
|
mTimerId = startTimer( CHECK_INTERVAL );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Destructor.
|
|
|
|
//
|
|
|
|
XAutoLock::~XAutoLock()
|
|
|
|
{
|
|
|
|
self = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// The time in seconds of continuous inactivity.
|
|
|
|
//
|
|
|
|
void XAutoLock::setTimeout(int t)
|
|
|
|
{
|
|
|
|
mTimeout = t;
|
|
|
|
resetTrigger();
|
|
|
|
}
|
|
|
|
|
|
|
|
void XAutoLock::setDPMS(bool s)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_DPMS
|
|
|
|
BOOL on;
|
|
|
|
CARD16 state;
|
|
|
|
DPMSInfo( tqt_xdisplay(), &state, &on );
|
|
|
|
if (!on)
|
|
|
|
s = false;
|
|
|
|
#endif
|
|
|
|
mDPMS = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Start watching Activity
|
|
|
|
//
|
|
|
|
void XAutoLock::start()
|
|
|
|
{
|
|
|
|
resetTrigger();
|
|
|
|
time(&mLastTimeout);
|
|
|
|
mActive = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Stop watching Activity
|
|
|
|
//
|
|
|
|
void XAutoLock::stop()
|
|
|
|
{
|
|
|
|
mActive = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Reset the trigger time.
|
|
|
|
//
|
|
|
|
void XAutoLock::resetTrigger()
|
|
|
|
{
|
|
|
|
mTrigger = time(0) + mTimeout;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Move the trigger time in order to postpone (repeat) emitting of timeout().
|
|
|
|
//
|
|
|
|
void XAutoLock::postpone()
|
|
|
|
{
|
|
|
|
mTrigger = time(0) + 60; // delay by 60sec
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Set the remaining time to 't', if it's shorter than already set.
|
|
|
|
//
|
|
|
|
void XAutoLock::setTrigger( time_t t )
|
|
|
|
{
|
|
|
|
if( t < mTrigger )
|
|
|
|
mTrigger = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Process new windows and check the mouse.
|
|
|
|
//
|
|
|
|
void XAutoLock::timerEvent(TQTimerEvent *ev)
|
|
|
|
{
|
|
|
|
if (ev->timerId() != mTimerId)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int (*oldHandler)(Display *, XErrorEvent *) = NULL;
|
|
|
|
if( !xautolock_useXidle && !xautolock_useMit )
|
|
|
|
{ // only the diy way needs special X handler
|
|
|
|
XSync( tqt_xdisplay(), False );
|
|
|
|
oldHandler = XSetErrorHandler(catchFalseAlarms);
|
|
|
|
}
|
|
|
|
|
|
|
|
xautolock_processQueue();
|
|
|
|
|
|
|
|
time_t now = time(0);
|
|
|
|
if ((now > mLastTimeout && now - mLastTimeout > TIME_CHANGE_LIMIT) ||
|
|
|
|
(mLastTimeout > now && mLastTimeout - now > TIME_CHANGE_LIMIT+1))
|
|
|
|
{
|
|
|
|
/* the time has changed in one large jump. This could be because
|
|
|
|
the date was changed, or the machine was suspended. We'll just
|
|
|
|
reset the triger. */
|
|
|
|
resetTrigger();
|
|
|
|
}
|
|
|
|
|
|
|
|
mLastTimeout = now;
|
|
|
|
|
|
|
|
xautolock_queryIdleTime( tqt_xdisplay());
|
|
|
|
xautolock_queryPointer( tqt_xdisplay());
|
|
|
|
|
|
|
|
if( !xautolock_useXidle && !xautolock_useMit )
|
|
|
|
XSetErrorHandler(oldHandler);
|
|
|
|
|
|
|
|
bool activate = false;
|
|
|
|
|
|
|
|
//kdDebug() << now << " " << mTrigger << endl;
|
|
|
|
if (now >= mTrigger)
|
|
|
|
{
|
|
|
|
resetTrigger();
|
|
|
|
activate = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_DPMS
|
|
|
|
BOOL on;
|
|
|
|
CARD16 state;
|
|
|
|
DPMSInfo( tqt_xdisplay(), &state, &on );
|
|
|
|
|
|
|
|
//kdDebug() << "DPMSInfo " << state << " " << on << endl;
|
|
|
|
// If DPMS is active, it makes XScreenSaverQueryInfo() report idle time
|
|
|
|
// that is always smaller than DPMS timeout (X bug I guess). So if DPMS
|
|
|
|
// saving is active, simply always activate our saving too, otherwise
|
|
|
|
// this could prevent locking from working.
|
|
|
|
if(state == DPMSModeStandby || state == DPMSModeSuspend || state == DPMSModeOff)
|
|
|
|
activate = true;
|
|
|
|
if(!on && mDPMS) {
|
|
|
|
activate = false;
|
|
|
|
#ifdef HAVE_XSCREENSAVER
|
|
|
|
XForceScreenSaver(tqt_xdisplay(), ScreenSaverReset );
|
|
|
|
#endif
|
|
|
|
resetTrigger();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_XSCREENSAVER
|
|
|
|
static XScreenSaverInfo* mitInfo = 0;
|
|
|
|
if (!mitInfo) mitInfo = XScreenSaverAllocInfo ();
|
|
|
|
if (XScreenSaverQueryInfo (tqt_xdisplay(), DefaultRootWindow (tqt_xdisplay()), mitInfo)) {
|
|
|
|
//kdDebug() << "XScreenSaverQueryInfo " << mitInfo->state << " " << ScreenSaverDisabled << endl;
|
|
|
|
if (mitInfo->state == ScreenSaverDisabled)
|
|
|
|
activate = false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(mActive && activate)
|
|
|
|
emit timeout();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool XAutoLock::x11Event( XEvent* ev )
|
|
|
|
{
|
|
|
|
xautolock_processEvent( ev );
|
|
|
|
// don't futher process key events that were received only because XAutoLock wants them
|
|
|
|
if( ev->type == KeyPress && !ev->xkey.send_event
|
|
|
|
&& !xautolock_useXidle && !xautolock_useMit
|
|
|
|
&& !TQWidget::find( ev->xkey.window ))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool XAutoLock::ignoreWindow( WId w )
|
|
|
|
{
|
|
|
|
if( w != tqt_xrootwin() && TQWidget::find( w ))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
void xautolock_resetTriggers()
|
|
|
|
{
|
|
|
|
self->resetTrigger();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
void xautolock_setTrigger( time_t t )
|
|
|
|
{
|
|
|
|
self->setTrigger( t );
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
int xautolock_ignoreWindow( Window w )
|
|
|
|
{
|
|
|
|
return self->ignoreWindow( w );
|
|
|
|
}
|