Source Code (Use browser search to find items of interest.)
Class Index
kdesktop'SaverEngine (./kdebase/kdesktop/lockeng.h:22)
class SaverEngine
: public QWidget,
virtual public KScreensaverIface
{
Q_OBJECT
public:
SaverEngine();
~SaverEngine();
/**
* Lock the screen
*/
virtual void lock();
/**
* Save the screen
*/
virtual void save();
/**
* return true if the screensaver is enabled
*/
virtual int isEnabled();
/**
* return true if the screen is currently blanked
*/
virtual int isBlanked();
/**
* Read and apply configuration.
*/
virtual void configure();
enum State { Waiting, Saving, Password };
protected:
virtual bool x11Event(XEvent *);
virtual void timerEvent(QTimerEvent *);
protected slots:
void idleTimeout();
void passwordChecked(KProcess *);
protected:
void readSaver(QString saver);
void createSaverWindow();
void hideSaverWindow();
void saveVRoot();
void setVRoot(Window win);
void removeVRoot(Window win);
bool grabKeyboard();
bool grabMouse();
bool grabInput();
void ungrabInput();
void startSaver();
void stopSaver();
bool startHack();
void stopHack();
void showPassDlg();
void hidePassDlg();
void setPassDlgTimeout(int t);
void killPassDlgTimeout();
void startCheckPassword();
bool handleKeyPress(XKeyEvent *xke);
protected:
bool mEnabled;
bool mLock;
int mPriority;
bool mLockOnce;
State mState;
PasswordDlg *mPassDlg;
Colormap mColorMap;
XAutoLock *mXAutoLock;
int mHidePassTimerId;
int mCheckPassTimerId;
KProcess mPassProc;
KProcess mHackProc;
bool mCheckingPass;
bool mPasswordStars;
int mRootWidth;
int mRootHeight;
QString mSaverExec;
// the original X screensaver parameters
int mXTimeout;
int mXInterval;
int mXBlanking;
int mXExposures;
};
kdesktop'SaverEngine::SaverEngine() (./kdebase/kdesktop/lockeng.cc:45)
SaverEngine::SaverEngine()
: QWidget(0L, "saver window", WStyle_Customize | WStyle_NoBorder),
DCOPObject("KScreensaverIface")
{
kapp->installX11EventFilter(this);
// Save X screensaver parameters
XGetScreenSaver(qt_xdisplay(), &mXTimeout, &mXInterval,
&mXBlanking, &mXExposures);
// Get root window size
XWindowAttributes rootAttr;
XGetWindowAttributes(qt_xdisplay(), RootWindow(qt_xdisplay(),
qt_xscreen()), &rootAttr);
mRootWidth = rootAttr.width;
mRootHeight = rootAttr.height;
// Add non-KDE path
KGlobal::dirs()->addResourceType("scrsav",
KGlobal::dirs()->kde_default("apps") +
"apps/ScreenSavers/");
// Add KDE specific screensaver path
KGlobal::dirs()->addResourceType("scrsav",
KGlobal::dirs()->kde_default("apps") +
"System/ScreenSavers/");
mState = Waiting;
mPassDlg = 0;
mHidePassTimerId = 0;
mCheckPassTimerId = 0;
mCheckingPass = false;
mXAutoLock = 0;
mEnabled = false;
mLockOnce = false;
// virtual root property
gXA_VROOT = XInternAtom (qt_xdisplay(), "__SWM_VROOT", False);
createSaverWindow();
connect(&mPassProc, SIGNAL(processExited(KProcess *)),
SLOT(passwordChecked(KProcess *)));
configure();
}
//---------------------------------------------------------------------------
//
// Destructor - usual cleanups.
//
kdesktop'SaverEngine::~SaverEngine() (./kdebase/kdesktop/lockeng.cc:96)
SaverEngine::~SaverEngine()
{
hidePassDlg();
if (mXAutoLock)
{
delete mXAutoLock;
}
// Restore X screensaver parameters
XSetScreenSaver(qt_xdisplay(), mXTimeout, mXInterval, mXBlanking,
mXExposures);
}
//---------------------------------------------------------------------------
kdesktop'SaverEngine::lock() (./kdebase/kdesktop/lockeng.cc:111)
void SaverEngine::lock()
{
if (mState == Waiting)
{
mLockOnce = true;
startSaver();
}
}
//---------------------------------------------------------------------------
kdesktop'SaverEngine::save() (./kdebase/kdesktop/lockeng.cc:121)
void SaverEngine::save()
{
if (mState == Waiting)
{
startSaver();
}
}
//---------------------------------------------------------------------------
kdesktop'SaverEngine::isEnabled() (./kdebase/kdesktop/lockeng.cc:130)
int SaverEngine::isEnabled()
{
return mEnabled;
}
//---------------------------------------------------------------------------
kdesktop'SaverEngine::isBlanked() (./kdebase/kdesktop/lockeng.cc:136)
int SaverEngine::isBlanked()
{
return (mState != Waiting);
}
//---------------------------------------------------------------------------
//
// Read and apply configuration.
//
kdesktop'SaverEngine::configure() (./kdebase/kdesktop/lockeng.cc:145)
void SaverEngine::configure()
{
// If we aren't in a suitable state, we will not reconfigure.
if (mState != Waiting)
{
return;
}
if (mXAutoLock)
{
delete mXAutoLock;
mXAutoLock = 0;
}
// create a new config obj to ensure we read the latest options
KConfig *config = new KConfig( "kdesktoprc", true);
config->setGroup("ScreenSaver");
mEnabled = config->readBoolEntry("Enabled", false);
mLock = config->readBoolEntry("Lock", false);
mPriority = config->readNumEntry("Priority", 0);
if (mPriority < 0) mPriority = 0;
if (mPriority > 19) mPriority = 19;
int timeout = config->readNumEntry("Timeout", 300);
mPasswordStars = config->readBoolEntry("PasswordAsStars", true);
QString saver = config->readEntry("Saver");
if (mEnabled)
{
readSaver(saver);
mXAutoLock = new XAutoLock();
connect(mXAutoLock, SIGNAL(timeout()), SLOT(idleTimeout()));
mXAutoLock->setTimeout(timeout);
mXAutoLock->start();
XSetScreenSaver(qt_xdisplay(), 0, mXInterval, mXBlanking, mXExposures);
kdDebug(1204) << "Saver Engine started" << endl;
}
else
{
mSaverExec = QString::null;
XSetScreenSaver(qt_xdisplay(), mXTimeout, mXInterval, mXBlanking,
mXExposures);
kdDebug(1204) << "Saver Engine disabled" << endl;
}
delete config;
}
//---------------------------------------------------------------------------
//
// Read the command line needed to run the screensaver given a .desktop file.
//
kdesktop'SaverEngine::readSaver() (./kdebase/kdesktop/lockeng.cc:202)
void SaverEngine::readSaver(QString saver)
{
if (!saver.isEmpty())
{
QString file = locate("scrsav", saver);
debug("Reading saver: %s", saver.ascii());
KDesktopFile config(file, true);
if (config.hasActionGroup("Root"))
{
config.setActionGroup("Root");
mSaverExec = config.readEntry("Exec");
}
debug("Saver-exec: %s", mSaverExec.ascii());
}
}
//---------------------------------------------------------------------------
//
// Create a window to draw our screen saver on.
//
kdesktop'SaverEngine::createSaverWindow() (./kdebase/kdesktop/lockeng.cc:226)
void SaverEngine::createSaverWindow()
{
XWindowAttributes attrs;
XGetWindowAttributes(qt_xdisplay(), winId(), &attrs);
mColorMap = attrs.colormap;
// We only create the window once, but we reset its attributes every
// time.
// Set virtual root property
saveVRoot();
if (gVRoot)
{
removeVRoot(gVRoot);
}
setVRoot(winId());
XSetWindowAttributes attr;
if (mColorMap != None)
{
attr.colormap = mColorMap;
}
else
{
attr.colormap = DefaultColormapOfScreen(
ScreenOfDisplay(qt_xdisplay(), qt_xscreen()));
}
attr.event_mask = KeyPressMask | ButtonPressMask | MotionNotify |
VisibilityChangeMask | ExposureMask;
XChangeWindowAttributes(qt_xdisplay(), winId(),
CWEventMask | CWColormap, &attr);
erase();
// set NoBackground so that the saver can capture the current
// screen state if necessary
setBackgroundMode( QWidget::NoBackground );
QBitmap bm(1, 1, TRUE);
QCursor c(bm, bm);
setCursor( c );
setGeometry(0, 0, mRootWidth, mRootHeight);
hide();
debug("Saver window Id: %d", winId());
}
//---------------------------------------------------------------------------
//
// Hide the screensaver window
//
kdesktop'SaverEngine::hideSaverWindow() (./kdebase/kdesktop/lockeng.cc:277)
void SaverEngine::hideSaverWindow()
{
hide();
removeVRoot(winId());
if (gVRoot)
{
setVRoot(gVRoot);
gVRoot = 0;
}
XSync(qt_xdisplay(), False);
}
//---------------------------------------------------------------------------
//
// Save the current virtual root window
//
kdesktop'SaverEngine::saveVRoot() (./kdebase/kdesktop/lockeng.cc:293)
void SaverEngine::saveVRoot()
{
Window rootReturn, parentReturn, *children;
unsigned int numChildren;
Window root = kapp->desktop()->winId();
gVRoot = 0;
int (*oldHandler)(Display *, XErrorEvent *);
oldHandler = XSetErrorHandler(ignoreXError);
if (XQueryTree(qt_xdisplay(), root, &rootReturn, &parentReturn,
&children, &numChildren))
{
for (unsigned int i = 0; i < numChildren; i++)
{
Atom actual_type;
int actual_format;
unsigned long nitems, bytesafter;
Window *newRoot = (Window *)0;
if ((XGetWindowProperty(qt_xdisplay(), children[i], gXA_VROOT, 0, 1,
False, XA_WINDOW, &actual_type, &actual_format, &nitems, &bytesafter,
(unsigned char **) &newRoot) == Success) && newRoot)
{
gVRoot = *newRoot;
break;
}
}
if (children)
{
XFree((char *)children);
}
}
XSetErrorHandler(oldHandler);
}
//---------------------------------------------------------------------------
//
// Set the virtual root property
//
kdesktop'SaverEngine::setVRoot() (./kdebase/kdesktop/lockeng.cc:335)
void SaverEngine::setVRoot(Window win)
{
XChangeProperty(qt_xdisplay(), win, gXA_VROOT, XA_WINDOW, 32,
PropModeReplace, (unsigned char *)&win, 1);
}
//---------------------------------------------------------------------------
//
// Remove the virtual root property
//
kdesktop'SaverEngine::removeVRoot() (./kdebase/kdesktop/lockeng.cc:345)
void SaverEngine::removeVRoot(Window win)
{
XDeleteProperty (qt_xdisplay(), win, gXA_VROOT);
}
//---------------------------------------------------------------------------
//
// Grab the keyboard. Returns true on success
//
kdesktop'SaverEngine::grabKeyboard() (./kdebase/kdesktop/lockeng.cc:354)
bool SaverEngine::grabKeyboard()
{
int rv = XGrabKeyboard( qt_xdisplay(), QApplication::desktop()->winId(),
True, GrabModeAsync, GrabModeAsync, CurrentTime );
return (rv == GrabSuccess);
}
//---------------------------------------------------------------------------
//
// Grab the mouse. Returns true on success
//
kdesktop'SaverEngine::grabMouse() (./kdebase/kdesktop/lockeng.cc:366)
bool SaverEngine::grabMouse()
{
int rv = XGrabPointer( qt_xdisplay(), QApplication::desktop()->winId(),
True, ButtonPressMask
| ButtonReleaseMask | EnterWindowMask | LeaveWindowMask
| PointerMotionMask | PointerMotionHintMask | Button1MotionMask
| Button2MotionMask | Button3MotionMask | Button4MotionMask
| Button5MotionMask | ButtonMotionMask | KeymapStateMask,
GrabModeAsync, GrabModeAsync, None, cursor().handle(),
CurrentTime );
return (rv == GrabSuccess);
}
//---------------------------------------------------------------------------
//
// Grab keyboard and mouse. Returns true on success.
//
kdesktop'SaverEngine::grabInput() (./kdebase/kdesktop/lockeng.cc:384)
bool SaverEngine::grabInput()
{
XSync(qt_xdisplay(), False);
if (!grabKeyboard())
{
sleep(1);
if (!grabKeyboard())
{
return false;
}
}
if (!grabMouse())
{
sleep(1);
if (!grabMouse())
{
XUngrabKeyboard(qt_xdisplay(), CurrentTime);
return false;
}
}
return true;
}
//---------------------------------------------------------------------------
//
// Release mouse an keyboard grab.
//
kdesktop'SaverEngine::ungrabInput() (./kdebase/kdesktop/lockeng.cc:414)
void SaverEngine::ungrabInput()
{
XUngrabKeyboard(qt_xdisplay(), CurrentTime);
XUngrabPointer(qt_xdisplay(), CurrentTime);
}
//---------------------------------------------------------------------------
//
// Start the screen saver.
//
kdesktop'SaverEngine::startSaver() (./kdebase/kdesktop/lockeng.cc:424)
void SaverEngine::startSaver()
{
if (mState != Waiting)
{
kdWarning(1204) << "SaverEngine::startSaver() saver already active" << endl;
return;
}
kdDebug(1204) << "SaverEngine: starting saver" << endl;
if (!grabInput())
{
kdWarning(1204) << "SaverEngine::startSaver() grabInput() failed!!!!" << endl;
return;
}
mState = Saving;
if (mXAutoLock)
{
mXAutoLock->stop();
}
createSaverWindow();
move(0, 0);
show();
raise();
XSync(qt_xdisplay(), False);
if (startHack() == false)
{
// failed to start a hack. Just show a blank screen
setBackgroundColor(black);
}
}
//---------------------------------------------------------------------------
//
// Stop the screen saver.
//
kdesktop'SaverEngine::stopSaver() (./kdebase/kdesktop/lockeng.cc:461)
void SaverEngine::stopSaver()
{
if (mState == Waiting)
{
kdWarning(1204) << "SaverEngine::stopSaver() saver not active" << endl;
return;
}
kdDebug(1204) << "SaverEngine: stopping saver" << endl;
stopHack();
hideSaverWindow();
hidePassDlg();
if (mXAutoLock)
{
mXAutoLock->start();
}
mState = Waiting;
ungrabInput();
mLockOnce = false;
}
//---------------------------------------------------------------------------
//
kdesktop'SaverEngine::startHack() (./kdebase/kdesktop/lockeng.cc:483)
bool SaverEngine::startHack()
{
if (mSaverExec.isEmpty())
{
return false;
}
if (mHackProc.isRunning())
{
stopHack();
}
mHackProc.clearArguments();
QTextStream ts(&mSaverExec, IO_ReadOnly);
QString word;
ts >> word;
QString path = KStandardDirs::findExe(word);
if (!path.isEmpty())
{
mHackProc << path;
debug("Starting hack: %s", path.ascii());
while (!ts.atEnd())
{
ts >> word;
if (word == "%w")
{
word = word.setNum(winId());
}
mHackProc << word;
}
if (mHackProc.start() == true)
{
#ifdef HAVE_SETPRIORITY
setpriority(PRIO_PROCESS, mHackProc.getPid(), mPriority);
#endif
return true;
}
}
return false;
}
//---------------------------------------------------------------------------
//
kdesktop'SaverEngine::stopHack() (./kdebase/kdesktop/lockeng.cc:532)
void SaverEngine::stopHack()
{
if (mHackProc.isRunning())
{
mHackProc.kill();
}
}
//---------------------------------------------------------------------------
//
// Show the password dialog
//
kdesktop'SaverEngine::showPassDlg() (./kdebase/kdesktop/lockeng.cc:544)
void SaverEngine::showPassDlg()
{
if (mPassDlg)
{
hidePassDlg();
}
mPassDlg = new PasswordDlg(this);
mPassDlg->showStars(mPasswordStars);
mPassDlg->move((mRootWidth - mPassDlg->width())/2,
(mRootHeight - mPassDlg->height())/2);
mPassDlg->show();
setPassDlgTimeout(PASSDLG_HIDE_TIMEOUT);
}
//---------------------------------------------------------------------------
//
// Hide the password dialog
//
kdesktop'SaverEngine::hidePassDlg() (./kdebase/kdesktop/lockeng.cc:562)
void SaverEngine::hidePassDlg()
{
if (mPassDlg)
{
delete mPassDlg;
mPassDlg = 0;
killPassDlgTimeout();
}
}
//---------------------------------------------------------------------------
//
// Hide the password dialog in "t" seconds.
//
kdesktop'SaverEngine::setPassDlgTimeout() (./kdebase/kdesktop/lockeng.cc:576)
void SaverEngine::setPassDlgTimeout(int t)
{
if (mHidePassTimerId)
{
killTimer(mHidePassTimerId);
}
mHidePassTimerId = startTimer(t);
}
//---------------------------------------------------------------------------
//
// Kill the password dialog hide timer.
//
kdesktop'SaverEngine::killPassDlgTimeout() (./kdebase/kdesktop/lockeng.cc:589)
void SaverEngine::killPassDlgTimeout()
{
if (mHidePassTimerId)
{
killTimer(mHidePassTimerId);
mHidePassTimerId = 0;
}
}
//---------------------------------------------------------------------------
//
// XAutoLock has detected the required idle time.
//
kdesktop'SaverEngine::idleTimeout() (./kdebase/kdesktop/lockeng.cc:602)
void SaverEngine::idleTimeout()
{
startSaver();
}
//---------------------------------------------------------------------------
//
// X11 Event.
//
kdesktop'SaverEngine::x11Event() (./kdebase/kdesktop/lockeng.cc:611)
bool SaverEngine::x11Event(XEvent *event)
{
if (!mEnabled && mState == Waiting)
{
return false;
}
bool ret = false;
switch (event->type)
{
case KeyPress:
ret = handleKeyPress((XKeyEvent *)event);
break;
case ButtonPress:
case MotionNotify:
if (mState == Saving)
{
if (mLock || mLockOnce)
{
showPassDlg();
mState = Password;
}
else
{
stopSaver();
}
}
break;
case CreateNotify:
if (event->xcreatewindow.window == winId() ||
(mPassDlg && event->xcreatewindow.window == mPassDlg->winId()))
{
break;
}
if (mXAutoLock)
{
mXAutoLock->windowCreated(event->xcreatewindow.window);
}
break;
case VisibilityNotify:
if (event->xvisibility.state != VisibilityUnobscured &&
event->xvisibility.window == winId() &&
(mState == Saving || mState == Password))
{
raise();
QApplication::flushX();
}
break;
case ConfigureNotify:
// Workaround for bug in Qt 2.1, as advised by Matthias Ettrich (David)
if (event->xconfigure.window != event->xconfigure.event)
return true;
if (mState == Saving || mState == Password)
{
raise();
QApplication::flushX();
}
break;
}
return ret;
}
//---------------------------------------------------------------------------
//
// Handle key press event.
//
kdesktop'SaverEngine::handleKeyPress() (./kdebase/kdesktop/lockeng.cc:683)
bool SaverEngine::handleKeyPress(XKeyEvent *xke)
{
bool ret = false;
switch (mState)
{
case Waiting:
if (!xke->send_event && mXAutoLock)
{
mXAutoLock->keyPressed();
}
break;
case Password:
if (!mCheckingPass)
{
KeySym keysym = 0;
XComposeStatus compose;
char buffer[2] = "";
XLookupString(xke, buffer, 1, &keysym, &compose);
switch (keysym)
{
case XK_Escape:
hidePassDlg();
mState = Saving;
break;
case XK_Return:
startCheckPassword();
break;
default:
setPassDlgTimeout(PASSDLG_HIDE_TIMEOUT);
mPassDlg->keyPressed(xke);
}
}
ret = true;
break;
case Saving:
if (mLock || mLockOnce)
{
showPassDlg();
mState = Password;
}
else
{
stopSaver();
}
return true;
}
return ret;
}
//---------------------------------------------------------------------------
//
// Starts the kcheckpass process to check the user's password.
//
kdesktop'SaverEngine::startCheckPassword() (./kdebase/kdesktop/lockeng.cc:742)
void SaverEngine::startCheckPassword()
{
const char *passwd = mPassDlg->password().ascii();
if (passwd)
{
QString kcp_binName = locate("exe", "kcheckpass");
mPassProc.clearArguments();
mPassProc << kcp_binName;
bool ret = mPassProc.start(KProcess::NotifyOnExit, KProcess::Stdin);
if (ret == false)
{
debug("kcheckpass failed to start");
return;
}
// write Password to stdin
mPassProc.writeStdin(passwd, strlen(passwd));
mPassProc.closeStdin();
killPassDlgTimeout();
mCheckingPass = true;
}
}
//---------------------------------------------------------------------------
//
// The kcheckpass process has exited.
//
kdesktop'SaverEngine::passwordChecked() (./kdebase/kdesktop/lockeng.cc:773)
void SaverEngine::passwordChecked(KProcess *proc)
{
if (proc == &mPassProc)
{
if (mPassProc.normalExit() && (mPassProc.exitStatus() == 0))
{
stopSaver();
}
else
{
mPassDlg->showFailed();
mPassDlg->resetPassword();
setPassDlgTimeout(PASSDLG_HIDE_TIMEOUT);
}
mCheckingPass = false;
}
}
//---------------------------------------------------------------------------
//
// Handle our timer events.
//
kdesktop'SaverEngine::timerEvent() (./kdebase/kdesktop/lockeng.cc:796)
void SaverEngine::timerEvent(QTimerEvent *ev)
{
if (ev->timerId() == mHidePassTimerId && !mCheckingPass)
{
hidePassDlg();
mState = Saving;
}
}
//---------------------------------------------------------------------------