summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Spilsbury <sam.spilsbury@canonical.com>2011-07-17 03:50:59 +0800
committerSam Spilsbury <sam.spilsbury@canonical.com>2011-07-17 03:50:59 +0800
commit3bc653b212719083344613a2caf33394db237dca (patch)
tree741d22c8f91f660ddcbeffbbb34bce952cad884e
parent858e8afdf35cc9037ce43a7164755560ce218b89 (diff)
downloadlocker-3bc653b212719083344613a2caf33394db237dca.tar.gz
locker-3bc653b212719083344613a2caf33394db237dca.tar.bz2
Add an XScreenSaverTrigger, separate out the trigger logic, things just got
amazing
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/locker.cpp200
-rw-r--r--src/locker.h66
3 files changed, 252 insertions, 16 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4c8dff5..0214fb7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,4 +2,4 @@ find_package (Compiz REQUIRED)
include (CompizPlugin)
-compiz_plugin (locker PLUGINDEPS composite opengl)
+compiz_plugin (locker PLUGINDEPS composite opengl PKGDEPS xscrnsaver)
diff --git a/src/locker.cpp b/src/locker.cpp
index a083473..81ddbb5 100644
--- a/src/locker.cpp
+++ b/src/locker.cpp
@@ -8,6 +8,7 @@ namespace {
static LockerLockWindow *mWindowDefault = NULL;
static LockerLockBackground *mBackgroundDefault = NULL;
static Lockable *mLockableDefault = NULL;
+ static LockTrigger *mTriggerDefault = NULL;
}
LockerLockWindow *
@@ -55,6 +56,21 @@ Lockable::SetDefault (Lockable *b)
mLockableDefault = b;
}
+void
+LockTrigger::SetDefault (LockTrigger *t)
+{
+ if (mTriggerDefault)
+ delete mTriggerDefault;
+
+ mTriggerDefault = t;
+}
+
+LockTrigger *
+LockTrigger::Default ()
+{
+ return mTriggerDefault;
+}
+
void
SimpleLockerWindow::hide ()
@@ -190,32 +206,38 @@ void
LockerScreen::handleEvent (XEvent *event)
{
LockerLockWindow *lockWindow = LockerLockWindow::Default ();
+ LockTrigger *lockTrigger = LockTrigger::Default ();
bool processed = false;
+ /* FIXME */
+
+ XScreenSaverTrigger *xt = dynamic_cast <XScreenSaverTrigger *> (lockTrigger);
+ if (xt)
+ xt->processEvent (event);
+
+ TimerTrigger *tt = dynamic_cast <TimerTrigger *> (lockTrigger);
+ if (tt)
+ tt->processEvent (event);
+
switch (event->type)
{
case ButtonPress:
- wake ();
if (lockWindow && lockWindow->needsGrab () && mAnimationState == AnimationStateLocked)
processed = lockWindow->handleButtonPress ((XButtonEvent *) event);
break;
case ButtonRelease:
- wake ();
if (lockWindow && lockWindow->needsGrab () && mAnimationState == AnimationStateLocked)
processed = lockWindow->handleButtonRelease ((XButtonEvent *) event);
break;
case KeyPress:
- wake ();
if (lockWindow && lockWindow->needsGrab () && mAnimationState == AnimationStateLocked)
processed = lockWindow->handleKeyPress ((XKeyEvent *) event);
break;
case KeyRelease:
- wake ();
if (lockWindow && lockWindow->needsGrab () && mAnimationState == AnimationStateLocked)
processed = lockWindow->handleKeyRelease ((XKeyEvent *) event);
break;
case MotionNotify:
- wake ();
if (lockWindow && lockWindow->needsGrab () && mAnimationState == AnimationStateLocked)
processed = lockWindow->handleMotion ((XMotionEvent *) event);
break;
@@ -378,8 +400,8 @@ LockerScreen::wake ()
unlock ();
else
{
- mWaitTimer.setTimes (30000, 30000);
- mWaitTimer.start ();
+ //mWaitTimer.setTimes (30000, 30000);
+ //mWaitTimer.start ();
if (lockWindow)
lockWindow->show ();
@@ -422,6 +444,8 @@ LockerScreen::lock ()
bool
LockerScreen::unlock ()
{
+ LockTrigger *trigger = LockTrigger::Default ();
+
if (mAnimationState != AnimationStateUnlocking ||
mAnimationState != AnimationStateIdle)
mAnimationState = AnimationStateUnlocking;
@@ -432,7 +456,7 @@ LockerScreen::unlock ()
mGrabIndex = 0;
}
- mWaitTimer.setTimes (optionGetTimeout () * 1000, optionGetTimeout () * 1000);
+ trigger->unlocked ();
return false;
}
@@ -468,6 +492,141 @@ LockerWindow::isAnimatedWindow ()
return false;
}
+void
+XScreenSaverTrigger::unlocked ()
+{
+ XSetScreenSaver (dpy, timeout, interval, preferBlanking, allowExposures);
+}
+
+void
+XScreenSaverTrigger::processEvent (XEvent *ev)
+{
+ Lockable *lockable = Lockable::Default ();
+ XScreenSaverNotifyEvent *xssEvent;
+
+ switch ((ev->type & 0x7F) - eventBase)
+ {
+ case ScreenSaverNotify:
+ xssEvent = (XScreenSaverNotifyEvent *) ev;
+
+ if (xssEvent->state)
+ {
+ XSetScreenSaver (dpy, 0, interval, preferBlanking, allowExposures);
+ lockable->lock ();
+ }
+ else
+ lockable->wake ();
+ }
+}
+
+bool
+XScreenSaverTrigger::usable ()
+{
+ return eventBase != 0;
+}
+
+XScreenSaverTrigger::XScreenSaverTrigger (Display *dpy, Window root, unsigned int cTimeout) :
+ dpy (dpy),
+ root (root),
+ timeout (0),
+ interval (0),
+ preferBlanking (0),
+ allowExposures (0),
+ eventBase (0),
+ eventBit (0)
+{
+ int dummy;
+ long unsigned int mask = 0;
+ XSetWindowAttributes attr;
+
+ /* Make sure we can actually use xss */
+ if (XScreenSaverQueryExtension (dpy, &eventBase, &dummy))
+ {
+ eventBit = 0x7F; /* black magic */
+ /* Kill the old screensaver and ensure that it doesn't come back */
+ XGetScreenSaver (dpy, &timeout, &interval, &preferBlanking, &allowExposures);
+
+ /* It's disabled. Blargh */
+ if (!timeout)
+ {
+ compLogMessage ("locker", CompLogLevelWarn, "XScreenSaverIntegration: no timeout has been set." \
+ " this usually means that XScreenSaver is disabled. Enable it to get integration " \
+ "with that. Using %i as the timeout", cTimeout);
+ XSetScreenSaver (dpy, cTimeout, interval, preferBlanking, allowExposures);
+
+ timeout = cTimeout;
+ }
+
+ XScreenSaverSetAttributes (dpy, root, -100, -100, 1, 1, 0,
+ CopyFromParent, CopyFromParent, DefaultVisual (dpy, XDefaultScreen (dpy)),
+ mask, &attr);
+ XScreenSaverSelectInput (screen->dpy (), root, ScreenSaverNotifyMask);
+ }
+ else
+ {
+ compLogMessage ("locker", CompLogLevelWarn, "Unable to use the XScreenSaver extension!");
+ }
+}
+
+XScreenSaverTrigger::~XScreenSaverTrigger ()
+{
+ XSetScreenSaver (dpy, timeout, interval, preferBlanking, allowExposures);
+
+ XScreenSaverSelectInput (dpy, root, 0);
+ XScreenSaverUnsetAttributes (dpy, root);
+}
+
+void
+TimerTrigger::unlocked ()
+{
+ mTimer.setTimes (mTimeout * 1000, mTimeout * 1000);
+ mTimer.start ();
+}
+
+bool
+TimerTrigger::check ()
+{
+ Lockable *lockable = Lockable::Default ();
+
+ if (lockable)
+ {
+ if (!mLocked)
+ return lockable->lock ();
+ else
+ return lockable->wake ();
+ }
+
+ return false;
+}
+
+void
+TimerTrigger::processEvent (XEvent *event)
+{
+ Lockable *lockable = Lockable::Default ();
+
+ if (!lockable)
+ return;
+
+ switch (event->type)
+ {
+ case ButtonPress:
+ case ButtonRelease:
+ case KeyPress:
+ case KeyRelease:
+ case MotionNotify:
+ lockable->wake ();
+ break;
+ }
+}
+
+TimerTrigger::TimerTrigger (unsigned int timeout) :
+ mTimeout (timeout)
+{
+ mTimer.setCallback (boost::bind (&TimerTrigger::check, this));
+ mTimer.setTimes (timeout * 1000, timeout * 1000);
+ mTimer.start ();
+}
+
LockerScreen::LockerScreen (CompScreen *s) :
PluginClassHandler <LockerScreen, CompScreen> (s),
cScreen (CompositeScreen::get (screen)),
@@ -479,21 +638,34 @@ LockerScreen::LockerScreen (CompScreen *s) :
Lockable::mLockerWindow = new SimpleLockerWindow ();
Lockable::mLockerBackground = new SimpleLockerBackground ();
+ /* Attempt to create an XSS Trigger first,
+ * then change it later */
+ XScreenSaverTrigger *xssTrigger = new XScreenSaverTrigger (screen->dpy (), screen->root (), optionGetTimeout ());
+ TimerTrigger *timerTrigger = NULL;
+
+ if (!xssTrigger->usable ())
+ {
+ delete xssTrigger;
+
+ timerTrigger = new TimerTrigger (optionGetTimeout ());
+ Lockable::mTrigger = timerTrigger;
+ }
+ else
+ Lockable::mTrigger = xssTrigger;
+
ScreenInterface::setHandler (screen);
CompositeScreenInterface::setHandler (cScreen);
GLScreenInterface::setHandler (gScreen);
- LockerLockWindow::SetDefault (mLockerWindow);
- LockerLockBackground::SetDefault (mLockerBackground);
+ LockerLockWindow::SetDefault (Lockable::mLockerWindow);
+ LockerLockBackground::SetDefault (Lockable::mLockerBackground);
+ LockTrigger::SetDefault (Lockable::mTrigger);
Lockable::SetDefault (this);
-
- mWaitTimer.setCallback (boost::bind (&LockerScreen::lock, this));
- mWaitTimer.setTimes (optionGetTimeout () * 1000, optionGetTimeout () * 1000);
- mWaitTimer.start ();
}
LockerScreen::~LockerScreen ()
{
+ LockTrigger::SetDefault (NULL);
LockerLockWindow::SetDefault (NULL);
LockerLockBackground::SetDefault (NULL);
Lockable::SetDefault (NULL);
diff --git a/src/locker.h b/src/locker.h
index 8581c33..2be02fa 100644
--- a/src/locker.h
+++ b/src/locker.h
@@ -9,6 +9,8 @@
#include "locker_options.h"
+#include <X11/extensions/scrnsaver.h>
+
class LockerLockWindow :
public CompRect
{
@@ -28,7 +30,6 @@ public:
virtual bool handleButtonRelease (XButtonEvent *xb) { return false; };
virtual bool handleMotion (XMotionEvent *xm) { return false; };
-
virtual CompRegion & damage () = 0;
static void
@@ -98,6 +99,66 @@ private:
CompRegion mDamage;
};
+class LockTrigger
+{
+public:
+ LockTrigger () {}
+ virtual ~LockTrigger () {}
+
+ virtual void unlocked () = 0;
+
+ static LockTrigger *
+ Default ();
+
+ static void
+ SetDefault (LockTrigger *);
+};
+
+class XScreenSaverTrigger :
+ public LockTrigger
+{
+public:
+
+ XScreenSaverTrigger (Display *, Window root, unsigned int timeout);
+ ~XScreenSaverTrigger ();
+
+ bool usable ();
+ void processEvent (XEvent *);
+ void unlocked ();
+
+private:
+
+ Display *dpy;
+ Window root;
+
+ int timeout;
+ int interval;
+ int preferBlanking;
+ int allowExposures;
+
+ int eventBase;
+ int eventBit;
+};
+
+/* Not exactly reliable */
+class TimerTrigger :
+ public LockTrigger
+{
+public:
+
+ TimerTrigger (unsigned int timeout);
+
+ void processEvent (XEvent *);
+ bool check ();
+ void unlocked ();
+
+private:
+
+ CompTimer mTimer;
+ unsigned int mTimeout;
+ bool mLocked;
+};
+
class Lockable
{
public:
@@ -119,8 +180,11 @@ protected:
LockerLockWindow *mLockerWindow;
LockerLockBackground *mLockerBackground;
+ LockTrigger *mTrigger;
};
+
+
class LockerScreen :
public PluginClassHandler <LockerScreen, CompScreen>,
public ScreenInterface,