Bug 117513 - Kopete should ignore activity when the screen is locked with the KDE screensaver
Summary: Kopete should ignore activity when the screen is locked with the KDE screensaver
Status: RESOLVED FIXED
Alias: None
Product: kopete
Classification: Applications
Component: libkopete (show other bugs)
Version: unspecified
Platform: Debian testing Linux
: NOR normal
Target Milestone: ---
Assignee: Kopete Developers
URL:
Keywords:
: 118437 119767 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-12-02 14:13 UTC by Isaac Wilcox
Modified: 2010-07-25 04:31 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Patch to fix auto-away (6.79 KB, patch)
2006-01-29 18:36 UTC, Isaac Wilcox
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Isaac Wilcox 2005-12-02 14:13:41 UTC
Version:            (using KDE KDE 3.4.2)
Installed from:    Debian testing/unstable Packages

When I set myself away in kopete by locking the screen using the KDE screensaver (and I only got that working when I added debug info - see bug 92949), activity on the locked screen sets me active in kopete.  It shouldn't.  If the screen is locked I can't be active because I can't possibly be using my computer - it's probably my coworker borrowing my chair, or the cleaner lovingly cleaning my mouse and keyboard.

I think this is because XQueryPointer() (called in libkopete/kopeteaway.cpp) detects pointer motion even when the screen is locked with the KDE screensaver, and ditto the X idle time detection.

I propose we check whether the screen is locked using the DCOP call kdesktop::KScreensaverIface::isBlanked() when we see apparent activity from XQueryPointer() or X's idle time counter.  If the user is using the KDE screensaver and it's blanked (note that isBlanked() DWIM and returns true when the screen is locked, too - even if you're actively attempting to type in a password at the point of the call), then we should ignore the apparent activity.  If the user isn't using the KDE screensaver or if the screen isn't blanked, we can revert to the existing behaviour, which isn't better but is at least no worse.
Comment 1 Matt Rogers 2005-12-13 00:17:21 UTC
Perhaps you can write a patch?
Comment 2 Isaac Wilcox 2005-12-13 12:57:38 UTC
A patch is in the works.  I've been busy the last two weeks looking for and moving into a new house, but it'll appear soon.
Comment 3 Matt Rogers 2005-12-16 14:23:59 UTC
*** Bug 118437 has been marked as a duplicate of this bug. ***
Comment 4 Isaac Wilcox 2006-01-29 18:33:53 UTC
OK, here's a patch (below).  It also hopefully fixes bug 92949 and bug 120989.

It correctly sets me away when I reach my autoaway timeout, when I lock the screen manually and when I start the screensaver in non-locking mode, and in all three cases I remain set away until I move the mouse or press a key.  I haven't tried it with a screensaver that kicks in by itself, but I'm sure that'll work.

There's one small bit I'm not happy with, which is that if you unlock the screen but do nothing else you don't get set active.  I tried hooking the KDE_stop_screensaver() signal up to call setActive() in kopete/kopeteiface.cpp in just the same way as KDE_start_screensaver() calls setAutoAway(), but it never seemed to trigger.  Didn't look into why, but I left the DCOP connection in there in case it's a bug somewhere else that gets fixed later.

Obviously most people unlocking their screen will proceed to do something and thus get set active in the normal way so this won't be a problem, but it'd just be that bit cleaner if the DCOP connection worked.

Seeing as some people seem able to reproduce this bug and some don't, it'd be nice to get both someone else who can reproduce it to try this patch out and confirm it works, and someone else who can't reproduce it eyeballing the code and trying it to confirm that it at least doesn't make things any worse for people without the bug.

Cheers,

Zak (Isaac Wilcox)
Comment 5 Isaac Wilcox 2006-01-29 18:36:39 UTC
Created attachment 14445 [details]
Patch to fix auto-away
Comment 6 Matt Rogers 2006-01-31 03:59:23 UTC
*** Bug 119767 has been marked as a duplicate of this bug. ***
Comment 7 Matt Rogers 2006-02-19 06:44:17 UTC
SVN commit 511207 by mattr:

Apply the patch from bug 117513 to fix several auto away issues with the code
that does this.

Patch by Issac Wilcox. Thanks so much for the patch!

BUG: 120989
BUG: 92949
BUG: 117513



 M  +3 -0      kopete/kopeteiface.cpp  
 M  +74 -15    libkopete/kopeteaway.cpp  
 M  +11 -3     libkopete/kopeteaway.h  


--- branches/kopete/0.12/kopete/kopete/kopeteiface.cpp #511206:511207
@@ -48,6 +48,9 @@
 		disconnectDCOPSignal("kdesktop", "KScreensaverIface",
 			"KDE_start_screensaver()", "setAutoAway()");
 	}
+	// FIXME: AFAICT, this never seems to fire.
+	connectDCOPSignal("kdesktop", "KScreensaverIface",
+		"KDE_stop_screensaver()", "setActive()", false);
 }
 
 QStringList KopeteIface::contacts()
--- branches/kopete/0.12/kopete/libkopete/kopeteaway.cpp #511206:511207
@@ -32,6 +32,7 @@
 #include <kconfig.h>
 #include <qtimer.h>
 #include <kapplication.h>
+#include <dcopref.h>
 
 #include <klocale.h>
 #include <kglobal.h>
@@ -122,10 +123,19 @@
 #ifdef Q_WS_X11
 	d->xIdleTime = 0;
 #endif
+	kdDebug(14010) << k_funcinfo << "Idle detection methods:" << endl;
+	kdDebug(14010) << k_funcinfo << "\tKScreensaverIface::isBlanked()" << endl;
+#ifdef Q_WS_X11
+	kdDebug(14010) << k_funcinfo << "\tX11 XQueryPointer()" << endl;
+#endif
 	if (d->useXidle)
-		kdDebug(14010) << "using X11 Xidle extension" << endl;
-	if(d->useMit)
-		kdDebug(14010) << "using X11 MIT Screensaver extension" << endl;
+	{
+		kdDebug(14010) << k_funcinfo << "\tX11 Xidle extension" << endl;
+	}
+	if (d->useMit)
+	{
+		kdDebug(14010) << k_funcinfo << "\tX11 MIT Screensaver extension" << endl;
+	}
 
 
 	load();
@@ -165,7 +175,7 @@
 	d->timer->start(4000);
 
 	//init the time and other
-	setActivity();
+	setActive();
 }
 
 Kopete::Away::~Away()
@@ -264,6 +274,42 @@
 
 void Kopete::Away::slotTimerTimeout()
 {
+	// Time to check whether we're active or autoaway.  We basically have two
+	// bits of info to go on - KDE's screensaver status
+	// (KScreenSaverIface::isBlanked()) and the X11 activity detection.
+	//
+	// Note that isBlanked() is a slight of a misnomer.  It returns true if we're:
+	//  - using a non-locking screensaver, which is running, or
+	//  - using a locking screensaver which is still locked, regardless of
+	//    whether the user is trying to unlock it right now
+	// Either way, it's only worth checking for activity if the screensaver
+	// isn't blanked/locked, because activity while blanked is impossible and
+	// activity while locked never matters (if there is any, it's probably just
+	// the cleaner wiping the keyboard :).
+
+	DCOPRef screenSaver("kdesktop", "KScreensaverIface");
+	DCOPReply isBlanked = screenSaver.call("isBlanked");
+	if (!(isBlanked.isValid() && isBlanked.type == "bool" && ((bool)isBlanked)))
+	{
+		// DCOP failed, or returned something odd, or the screensaver is
+		// inactive, so check for activity the X11 way.  It's only worth
+		// checking for autoaway if there's no activity, and because
+		// Screensaver blanking/locking implies autoAway activation (see
+		// KopeteIface::KopeteIface()), only worth checking autoAway when the
+		// screensaver isn't running.
+		if (isActivity())
+		{
+			setActive();
+		}
+		else if (!d->autoaway && d->useAutoAway && idleTime() > d->awayTimeout)
+		{
+			setAutoAway();
+		}
+	}
+}
+
+bool Kopete::Away::isActivity()
+{
 	// Copyright (c) 1999 Martin R. Jones <mjones@kde.org>
 	//
 	// KDE screensaver engine
@@ -271,6 +317,8 @@
 	// This module is a heavily modified xautolock.
 	// In fact as of KDE 2.0 this code is practically unrecognisable as xautolock.
 
+	bool activity = false;
+
 #ifdef Q_WS_X11
 	Display *dsp = qt_xdisplay();
 	Window           dummy_w;
@@ -305,9 +353,9 @@
 			}
 		}
 	}
-#endif
+
 	// =================================================================================
-#ifdef Q_WS_X11
+
 	Time xIdleTime = 0; // millisecs since last input event
 
 	#ifdef HasXidle
@@ -332,10 +380,19 @@
 
 	// =================================================================================
 
-	if (root_x != d->mouse_x || root_y != d->mouse_y || mask != d->mouse_mask || xIdleTime < d->xIdleTime+2000)
+	// Only check idle time if we have some way of measuring it, otherwise if
+	// we've neither Mit nor Xidle it'll still be zero and we'll always appear active.
+	// FIXME: what problem does the 2000ms fudge solve?
+	if (root_x != d->mouse_x || root_y != d->mouse_y || mask != d->mouse_mask
+		|| ((d->useXidle || d->useMit) && xIdleTime < d->xIdleTime + 2000))
 	{
-		if(d->mouse_x!=-1) //we just gone autoaway, not activity this time
-			setActivity();
+		// -1 => just gone autoaway, ignore apparent activity this time round
+		// anything else => genuine activity
+		// See setAutoAway().
+		if (d->mouse_x != -1)
+		{
+			activity = true;
+		}
 		d->mouse_x = root_x;
 		d->mouse_y = root_y;
 		d->mouse_mask = mask;
@@ -344,13 +401,10 @@
 #endif // Q_WS_X11
 	// =================================================================================
 
-	if(!d->autoaway && d->useAutoAway && idleTime() > d->awayTimeout)
-	{
-		setAutoAway();
-	}
+	return activity;
 }
 
-void Kopete::Away::setActivity()
+void Kopete::Away::setActive()
 {
 //	kdDebug(14010) << k_funcinfo << "Found activity on desktop, resetting away timer" << endl;
 	d->idleTime.start();
@@ -381,7 +435,12 @@
 
 void Kopete::Away::setAutoAway()
 {
-	d->mouse_x=-1; //do not go availiable automaticaly after
+	// A value of -1 in mouse_x indicates to checkActivity() that next time it
+	// fires it should ignore any apparent idle/mouse/keyboard changes.
+	// I think the point of this is that if you manually start the screensaver
+	// then there'll unavoidably be some residual mouse/keyboard activity
+	// that should be ignored.
+	d->mouse_x = -1;
 
 //	kdDebug(14010) << k_funcinfo << "Going AutoAway!" << endl;
 	d->autoaway = true;
--- branches/kopete/0.12/kopete/libkopete/kopeteaway.h #511206:511207
@@ -139,6 +139,14 @@
 	 */
 	void save();
 
+	/**
+	 * @brief Check for activity using X11 methods
+	 * @return true if activity was detected, otherwise false
+	 *
+	 * Attempt to detect activity using a variety of X11 methods.
+	 */
+	bool isActivity();
+
 	//Away( const Away &rhs );
 	//Away &operator=( const Away &rhs );
 	static Away *instance;
@@ -150,14 +158,14 @@
 
 public slots:
 	/**
-	 * @brief Set the activity
+	 * @brief Mark the user active
 	 *
-	 * Plugins can set the activity if they discover activity by another way than the mouse or the keyboard
+	 * Plugins can mark the user active if they discover activity by another way than the mouse or the keyboard
 	 * (example, the motion auto away plugin)
 	 * this will reset the @ref idleTime to 0, and set all protocols to available (online) if the state was
 	 * set automatically to away because of idleness, and if they was previously online
 	 */
-	void setActivity();
+	void setActive();
 
 	/**
 	 * Use this method if you want to go in the autoaway mode.
Comment 8 Matt Rogers 2006-02-19 16:36:31 UTC
SVN commit 511336 by mattr:

backport patches for bugs 120989, 92949, and 117513
Should be in KDE 3.5.2 and the upcoming 0.12 release.

CCBUG: 120989, 92949, 117513



 M  +3 -0      kopete/kopeteiface.cpp  
 M  +74 -15    libkopete/kopeteaway.cpp  
 M  +11 -3     libkopete/kopeteaway.h  


--- branches/KDE/3.5/kdenetwork/kopete/kopete/kopeteiface.cpp #511335:511336
@@ -48,6 +48,9 @@
 		disconnectDCOPSignal("kdesktop", "KScreensaverIface",
 			"KDE_start_screensaver()", "setAutoAway()");
 	}
+	// FIXME: AFAICT, this never seems to fire.
+	connectDCOPSignal("kdesktop", "KScreensaverIface",
+		"KDE_stop_screensaver()", "setActive()", false);
 }
 
 QStringList KopeteIface::contacts()
--- branches/KDE/3.5/kdenetwork/kopete/libkopete/kopeteaway.cpp #511335:511336
@@ -32,6 +32,7 @@
 #include <kconfig.h>
 #include <qtimer.h>
 #include <kapplication.h>
+#include <dcopref.h>
 
 #include <klocale.h>
 #include <kglobal.h>
@@ -122,10 +123,19 @@
 #ifdef Q_WS_X11
 	d->xIdleTime = 0;
 #endif
+	kdDebug(14010) << k_funcinfo << "Idle detection methods:" << endl;
+	kdDebug(14010) << k_funcinfo << "\tKScreensaverIface::isBlanked()" << endl;
+#ifdef Q_WS_X11
+	kdDebug(14010) << k_funcinfo << "\tX11 XQueryPointer()" << endl;
+#endif
 	if (d->useXidle)
-		kdDebug(14010) << "using X11 Xidle extension" << endl;
-	if(d->useMit)
-		kdDebug(14010) << "using X11 MIT Screensaver extension" << endl;
+	{
+		kdDebug(14010) << k_funcinfo << "\tX11 Xidle extension" << endl;
+	}
+	if (d->useMit)
+	{
+		kdDebug(14010) << k_funcinfo << "\tX11 MIT Screensaver extension" << endl;
+	}
 
 
 	load();
@@ -165,7 +175,7 @@
 	d->timer->start(4000);
 
 	//init the time and other
-	setActivity();
+	setActive();
 }
 
 Kopete::Away::~Away()
@@ -264,6 +274,42 @@
 
 void Kopete::Away::slotTimerTimeout()
 {
+	// Time to check whether we're active or autoaway.  We basically have two
+	// bits of info to go on - KDE's screensaver status
+	// (KScreenSaverIface::isBlanked()) and the X11 activity detection.
+	//
+	// Note that isBlanked() is a slight of a misnomer.  It returns true if we're:
+	//  - using a non-locking screensaver, which is running, or
+	//  - using a locking screensaver which is still locked, regardless of
+	//    whether the user is trying to unlock it right now
+	// Either way, it's only worth checking for activity if the screensaver
+	// isn't blanked/locked, because activity while blanked is impossible and
+	// activity while locked never matters (if there is any, it's probably just
+	// the cleaner wiping the keyboard :).
+
+	DCOPRef screenSaver("kdesktop", "KScreensaverIface");
+	DCOPReply isBlanked = screenSaver.call("isBlanked");
+	if (!(isBlanked.isValid() && isBlanked.type == "bool" && ((bool)isBlanked)))
+	{
+		// DCOP failed, or returned something odd, or the screensaver is
+		// inactive, so check for activity the X11 way.  It's only worth
+		// checking for autoaway if there's no activity, and because
+		// Screensaver blanking/locking implies autoAway activation (see
+		// KopeteIface::KopeteIface()), only worth checking autoAway when the
+		// screensaver isn't running.
+		if (isActivity())
+		{
+			setActive();
+		}
+		else if (!d->autoaway && d->useAutoAway && idleTime() > d->awayTimeout)
+		{
+			setAutoAway();
+		}
+	}
+}
+
+bool Kopete::Away::isActivity()
+{
 	// Copyright (c) 1999 Martin R. Jones <mjones@kde.org>
 	//
 	// KDE screensaver engine
@@ -271,6 +317,8 @@
 	// This module is a heavily modified xautolock.
 	// In fact as of KDE 2.0 this code is practically unrecognisable as xautolock.
 
+	bool activity = false;
+
 #ifdef Q_WS_X11
 	Display *dsp = qt_xdisplay();
 	Window           dummy_w;
@@ -305,9 +353,9 @@
 			}
 		}
 	}
-#endif
+
 	// =================================================================================
-#ifdef Q_WS_X11
+
 	Time xIdleTime = 0; // millisecs since last input event
 
 	#ifdef HasXidle
@@ -332,10 +380,19 @@
 
 	// =================================================================================
 
-	if (root_x != d->mouse_x || root_y != d->mouse_y || mask != d->mouse_mask || xIdleTime < d->xIdleTime+2000)
+	// Only check idle time if we have some way of measuring it, otherwise if
+	// we've neither Mit nor Xidle it'll still be zero and we'll always appear active.
+	// FIXME: what problem does the 2000ms fudge solve?
+	if (root_x != d->mouse_x || root_y != d->mouse_y || mask != d->mouse_mask
+		|| ((d->useXidle || d->useMit) && xIdleTime < d->xIdleTime + 2000))
 	{
-		if(d->mouse_x!=-1) //we just gone autoaway, not activity this time
-			setActivity();
+		// -1 => just gone autoaway, ignore apparent activity this time round
+		// anything else => genuine activity
+		// See setAutoAway().
+		if (d->mouse_x != -1)
+		{
+			activity = true;
+		}
 		d->mouse_x = root_x;
 		d->mouse_y = root_y;
 		d->mouse_mask = mask;
@@ -344,13 +401,10 @@
 #endif // Q_WS_X11
 	// =================================================================================
 
-	if(!d->autoaway && d->useAutoAway && idleTime() > d->awayTimeout)
-	{
-		setAutoAway();
-	}
+	return activity;
 }
 
-void Kopete::Away::setActivity()
+void Kopete::Away::setActive()
 {
 //	kdDebug(14010) << k_funcinfo << "Found activity on desktop, resetting away timer" << endl;
 	d->idleTime.start();
@@ -381,7 +435,12 @@
 
 void Kopete::Away::setAutoAway()
 {
-	d->mouse_x=-1; //do not go availiable automaticaly after
+	// A value of -1 in mouse_x indicates to checkActivity() that next time it
+	// fires it should ignore any apparent idle/mouse/keyboard changes.
+	// I think the point of this is that if you manually start the screensaver
+	// then there'll unavoidably be some residual mouse/keyboard activity
+	// that should be ignored.
+	d->mouse_x = -1;
 
 //	kdDebug(14010) << k_funcinfo << "Going AutoAway!" << endl;
 	d->autoaway = true;
--- branches/KDE/3.5/kdenetwork/kopete/libkopete/kopeteaway.h #511335:511336
@@ -139,6 +139,14 @@
 	 */
 	void save();
 
+	/**
+	 * @brief Check for activity using X11 methods
+	 * @return true if activity was detected, otherwise false
+	 *
+	 * Attempt to detect activity using a variety of X11 methods.
+	 */
+	bool isActivity();
+
 	//Away( const Away &rhs );
 	//Away &operator=( const Away &rhs );
 	static Away *instance;
@@ -150,14 +158,14 @@
 
 public slots:
 	/**
-	 * @brief Set the activity
+	 * @brief Mark the user active
 	 *
-	 * Plugins can set the activity if they discover activity by another way than the mouse or the keyboard
+	 * Plugins can mark the user active if they discover activity by another way than the mouse or the keyboard
 	 * (example, the motion auto away plugin)
 	 * this will reset the @ref idleTime to 0, and set all protocols to available (online) if the state was
 	 * set automatically to away because of idleness, and if they was previously online
 	 */
-	void setActivity();
+	void setActive();
 
 	/**
 	 * Use this method if you want to go in the autoaway mode.