[hamster-applet/windows] Implemented idle and screenlock detection
- From: Matthew Howle <mdhowle src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [hamster-applet/windows] Implemented idle and screenlock detection
- Date: Sun, 27 Mar 2011 08:35:36 +0000 (UTC)
commit daf93241486ad9ca73f93b5623bb4c95dfba3d11
Author: Matthew Howle <matthew howle org>
Date: Sun Mar 27 04:34:35 2011 -0400
Implemented idle and screenlock detection
src/hamster-time-tracker | 9 ++-
src/hamster/idle.py | 220 +++++++++++++++++++++-------------------------
2 files changed, 107 insertions(+), 122 deletions(-)
---
diff --git a/src/hamster-time-tracker b/src/hamster-time-tracker
index a138481..f77ca76 100755
--- a/src/hamster-time-tracker
+++ b/src/hamster-time-tracker
@@ -58,6 +58,10 @@ class ProjectHamster(object):
self.get_widget("today_box").add(self.treeview)
self.new_name.grab_focus()
+ #idle listener
+ self.IdleListener = idle.IdleListener()
+ self.IdleListener.connect('idle-changed', self.on_idle_changed)
+
# configuration
self.timeout_enabled = conf.get("enable_timeout")
self.notify_on_idle = conf.get("notify_on_idle")
@@ -285,15 +289,14 @@ class ProjectHamster(object):
def on_idle_changed(self, event, state):
# state values: 0 = active, 1 = idle
-
+
# refresh when we are out of idle
# for example, instantly after coming back from suspend
if state == 0:
self.refresh_hamster()
elif self.timeout_enabled and self.last_activity and \
self.last_activity.end_time is None:
- #TODO: need a Windows way to get idle time
- runtime.storage.stop_tracking(end_time = dt.datetime.now())
+ runtime.storage.stop_tracking(end_time = self.IdleListener.get_idle_from())
def on_workspace_changed(self, screen, previous_workspace):
if not previous_workspace:
diff --git a/src/hamster/idle.py b/src/hamster/idle.py
index f305db7..9aee8ac 100644
--- a/src/hamster/idle.py
+++ b/src/hamster/idle.py
@@ -17,122 +17,104 @@
# You should have received a copy of the GNU General Public License
# along with Project Hamster. If not, see <http://www.gnu.org/licenses/>.
#
-#import logging
-#import dbus
-#import datetime as dt
-#import gobject
-# TODO: Create a Windows alternative
-#class DbusIdleListener(gobject.GObject):
-# """
-# Listen for idleness coming from org.gnome.ScreenSaver
-#
-# Monitors org.gnome.ScreenSaver for idleness. There are two types,
-# 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 "ActiveChanged" and "Lock"
-# members coming from the org.gnome.ScreenSaver interface and the
-# and is_screen_locked members are updated appropriately.
-# """
-# __gsignals__ = {
-# "idle-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
-# }
-# def __init__(self):
-# gobject.GObject.__init__(self)
-#
-# self.screensaver_uri = "org.gnome.ScreenSaver"
-# self.screen_locked = False
-# self.idle_from = None
-# self.timeout_minutes = 0 # minutes after session is considered idle
-# self.idle_was_there = False # a workaround variable for pre 2.26
-#
-# 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='%s'" %
-# 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
-# """
-#
-# # We only care about stuff on this interface. We did filter
-# # for it above, but even so we still hear from ourselves
-# # (hamster messages).
-# if message.get_interface() != self.screensaver_uri:
-# return True
-#
-# member = message.get_member()
-#
-# if member in ("SessionIdleChanged", "ActiveChanged"):
-# logging.debug("%s -> %s" % (member, message.get_args_list()))
-#
-# idle_state = message.get_args_list()[0]
-# if idle_state:
-# self.idle_from = dt.datetime.now()
-#
-# # from gnome screensaver 2.24 to 2.28 they have switched
-# # configuration keys and signal types.
-# # luckily we can determine key by signal type
-# if member == "SessionIdleChanged":
-# delay_key = "/apps/gnome-screensaver/idle_delay"
-# else:
-# delay_key = "/desktop/gnome/session/idle_delay"
-#
-# client = gconf.client_get_default()
-# self.timeout_minutes = client.get_int(delay_key)
-#
-# else:
-# self.screen_locked = False
-# self.idle_from = None
-#
-# if member == "ActiveChanged":
-# # ActiveChanged comes before SessionIdleChanged signal
-# # as a workaround for pre 2.26, we will wait a second - maybe
-# # SessionIdleChanged signal kicks in
-# def dispatch_active_changed(idle_state):
-# if not self.idle_was_there:
-# self.emit('idle-changed', idle_state)
-# self.idle_was_there = False
-#
-# gobject.timeout_add_seconds(1, dispatch_active_changed, idle_state)
-#
-# else:
-# # dispatch idle status change to interested parties
-# self.idle_was_there = True
-# self.emit('idle-changed', idle_state)
-#
-# elif member == "Lock":
-# # in case of lock, lock signal will be sent first, followed by
-# # ActiveChanged and SessionIdle signals
-# logging.debug("Screen Lock Requested")
-# self.screen_locked = True
-#
-# return
-#
-#
-# def getIdleFrom(self):
-# if not self.idle_from:
-# return dt.datetime.now()
-#
-# if self.screen_locked:
-# return self.idle_from
-# else:
-# # Only subtract idle time from the running task when
-# # idleness is due to time out, not a screen lock.
-# return self.idle_from - dt.timedelta(minutes = self.timeout_minutes)
+import logging
+import datetime as dt
+import gobject
+import ctypes, ctypes.wintypes
+try:
+ import _winreg as winreg
+except ImportError:
+ try:
+ import winreg
+ except ImportError:
+ winreg = None
+
+class IdleListener(gobject.GObject):
+ """
+ Listen for idleness
+
+ Monitors the system for idleness. There are two types, implicit (due to
+ inactivity) and explicit (locked screen), that need to be handled differently.
+ An implicit idle state should subtract the time-to-become-idle (as specified
+ in the configuration) from the last activity but an explicit idle state should
+ not.
+ """
+
+ __gsignals__ = {
+ "idle-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
+ }
+ def __init__(self):
+ gobject.GObject.__init__(self)
+
+ self.screen_locked = False
+ self.idle_from = None
+ self.timeout = self.get_screensaver_timeout()
+ gobject.timeout_add_seconds(5, self.check_idle)
+
+ def check_idle(self):
+ # Check idleness or screen lock
+ idletime = self.get_idle_time()
+ self.screen_locked = self.is_screenlocked()
+ if idletime >= self.timeout or self.screen_locked:
+ if self.idle_from is None:
+ logging.debug("idle/screenlock detected")
+ self.idle_from = dt.datetime.now()
+ self.emit('idle-changed', 1)
+ elif self.idle_from is not None: # user is back
+ self.idle_from = None
+ self.emit('idle-changed', 0)
+
+ return True
+
+
+ def get_idle_time(self):
+ """ Returns the idle time in seconds """
+
+ class LASTINPUTINFO(ctypes.Structure):
+ """ LastInputInfo struct (http://msdn.microsoft.com/en-us/library/ms646272%28v=VS.85%29.aspx) """
+ _fields_ = [
+ ("cbSize", ctypes.wintypes.UINT),
+ ("dwTime", ctypes.wintypes.DWORD),
+ ]
+
+ lastinput = LASTINPUTINFO()
+ lastinput.cbSize = ctypes.sizeof(lastinput) # this member must be set to sizeof(LASTINPUTINFO)
+
+ ctypes.windll.user32.GetLastInputInfo(ctypes.byref(lastinput))
+ ticks = ctypes.windll.kernel32.GetTickCount() - lastinput.dwTime
+
+ return ticks / 1000.0 # convert milliseconds to seconds
+
+ def get_idle_from(self):
+ """ Return time when the user went idle """
+ if not self.idle_from:
+ return dt.datetime.now()
+
+ if self.screen_locked:
+ return self.idle_from
+ else:
+ return self.idle_from - dt.timedelta(seconds = self.timeout)
+
+ def get_screensaver_timeout(self):
+ """ Returns the Windows screensaver timeout (in seconds) """
+
+ if winreg == None: return 600 # default to 10 minutes
+
+ try:
+ key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Control Panel\Desktop")
+ value = winreg.QueryValueEx(key, "ScreenSaveTimeOut")[0]
+ key.Close()
+ return int(value)
+ except:
+ logging.warn("WARNING - Failed to get screensaver timeout")
+ return 600
+
+
+ def is_screenlocked(self):
+ # if screen is locked, GetForegroundWindow() returns 0
+ if ctypes.windll.user32.GetForegroundWindow() == 0:
+ return True
+ else:
+ return False
+
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]