hamster-applet r826 - trunk/hamster



Author: tbaugis
Date: Mon Mar  2 10:06:37 2009
New Revision: 826
URL: http://svn.gnome.org/viewvc/hamster-applet?rev=826&view=rev

Log:
respect session lock and do not stop timer
 (sometimes locking computer is not the same as
stopping working on a task)

Patch by  Uri Okrent

Fixes bug 561454

Modified:
   trunk/hamster/applet.py
   trunk/hamster/idle.py

Modified: trunk/hamster/applet.py
==============================================================================
--- trunk/hamster/applet.py	(original)
+++ trunk/hamster/applet.py	Mon Mar  2 10:06:37 2009
@@ -210,6 +210,9 @@
             name = dbus.service.BusName(HAMSTER_URI, dbus.SessionBus())
             self.dbusController = HamsterDbusController(bus_name = name)
 
+            # Set up connection to the screensaver
+            self.dbusIdleListener = idle.DbusIdleListener()
+
             # let's also attach our listeners here
             bus = dbus.SessionBus()
             bus.add_signal_receiver(self.on_idle_changed,
@@ -375,8 +378,13 @@
         # stop tracking task if computer is idle for X minutes
         if self.timeout_enabled and self.last_activity and \
            self.last_activity['end_time'] == None:
-            idle_minutes = idle.getIdleSec() / 60.0
-            if idle_minutes > 0:
+            if self.dbusIdleListener.is_idle:
+                # Only subtract idle time from the running task when
+                # idleness is due to time out, not a screen lock.
+                if self.dbusIdleListener.is_screen_locked:
+                    idle_minutes = 0
+                else:
+                    idle_minutes = idle.getIdleSec() / 60.0
                 current_time = datetime.datetime.now()
                 idle_from = current_time - datetime.timedelta(minutes = idle_minutes)
                 storage.touch_fact(self.last_activity, end_time = idle_from)

Modified: trunk/hamster/idle.py
==============================================================================
--- trunk/hamster/idle.py	(original)
+++ trunk/hamster/idle.py	Mon Mar  2 10:06:37 2009
@@ -18,10 +18,9 @@
 # along with Project Hamster.  If not, see <http://www.gnu.org/licenses/>.
 
 import dbus
+from dbus.lowlevel import Message
 import gconf
 
-# TODO - since we don't allow to specify idle minutes, we should just listen
-# to the SessionIdleChanged signal from org.gnome.Screensaver
 def getIdleSec():
     try:
         bus = dbus.SessionBus()
@@ -38,4 +37,88 @@
     
     return idle_time
 
-    
\ No newline at end of file
+
+class DbusIdleListener(object):
+    """
+    Listen for idleness coming from org.gnome.ScreenSaver
+
+    Monitors org.gnome.ScreenSaver for idleness. There are two types
+    (that I know of), implicit (due to inactivity) and explicit (lock
+    screen), that need to be handled differently. An implicit idle
+    state should subtract the time-to-become-idle (as specified in the
+    gconf) from the last activity, but an explicit idle state should
+    not.
+
+    The signals are inspected for the "SessionIdleChanged" and "Lock"
+    members coming from the org.gnome.ScreenSaver interface and the
+    is_idle, and is_screen_locked members are updated appropriately.
+    """
+    def __init__(self):
+        self.screensaver_uri = "org.gnome.ScreenSaver"
+
+        self.is_idle = False
+        self.is_screen_locked = False
+
+        try:
+            self.bus = dbus.SessionBus()
+        except:
+            return 0
+        # Listen for chatter on the screensaver interface.
+        # We cannot just add additional match strings to narrow down
+        # what we hear because match strings are ORed together.
+        # E.g., if we were to make the match string
+        # "interface='org.gnome.ScreenSaver', type='method_call'",
+        # we would not get only screensaver's method calls, rather
+        # we would get anything on the screensaver interface, as well
+        # as any method calls on *any* interface. Therefore the
+        # bus_inspector needs to do some additional filtering.
+        self.bus.add_match_string_non_blocking(
+                "interface='" + self.screensaver_uri + "'")
+
+        self.bus.add_message_filter(self.bus_inspector)
+
+
+    def bus_inspector(self, bus, message):
+        """
+        Inspect the bus for screensaver messages of interest
+
+        Namely, we are watching for messages on the screensaver
+        interface.  If it's a signal type for SessionIdleChanged,
+        we set our internal is_idle state to that value (the signal
+        is a boolean).  If its a method call with type "Lock" then
+        the user requested to lock the screen so we set our internal
+        lock state to true.
+
+        When the SessionIdleChanged signal is false, it means we are
+        returning from the locked/idle state, so both is_idle and
+        is_screen_locked are reset to False.
+        """
+        # We only care about stuff on this interface.  Yes we did filter
+        # for it above, but even so we still hear from ourselves
+        # (hamster messages).
+        if not message.get_interface() == self.screensaver_uri:
+            return
+
+        # Signal type messages have a value of 4, and method_call type
+        # ones have a value of 1.  I'm not sure how important it is to
+        # verify that SessionIdleChanged on the screensaver interface
+        # is actually a "signal" and not some other type of message
+        # but I'll make sure just to be safe.  Same goes for the Lock
+        # member.
+        if message.get_member() == "SessionIdleChanged" and \
+           message.get_type() == 4:
+            if __debug__:
+                print "SessionIdleChanged ->", message.get_args_list()
+            idle_state = message.get_args_list()[0]
+            if idle_state:
+                self.is_idle = True
+            else:
+                self.is_idle = False
+                self.is_screen_locked = False
+        elif message.get_member() == "Lock" and \
+             message.get_type() == 1:
+            if __debug__:
+                print "Screen Lock Requested"
+            self.is_screen_locked = True
+
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]