Created
February 23, 2011 08:03
-
-
Save tstone2077/840156 to your computer and use it in GitHub Desktop.
This is a little class wrapper to detect if the system is idle on a windows system.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import platform | |
import threading | |
import time | |
if platform.system() == "Windows": | |
import ctypes, ctypes.wintypes | |
# http://msdn.microsoft.com/en-us/library/ms646272(VS.85).aspx | |
# typedef struct tagLASTINPUTINFO { | |
# UINT cbSize; | |
# DWORD dwTime; | |
# } LASTINPUTINFO, *PLASTINPUTINFO; | |
class LASTINPUTINFO(ctypes.Structure): | |
_fields_ = [ | |
('cbSize', ctypes.wintypes.UINT), | |
('dwTime', ctypes.wintypes.DWORD), | |
] | |
class IdleThread(threading.Thread): | |
""" | |
This class will raise an event every time the system is | |
considered Idle. | |
""" | |
def __init__(self,idleTime,idleEvent,continueEvent): | |
self.callback = None | |
self.idleTime = idleTime | |
self.idleEvent = idleEvent | |
self.continueEvent = continueEvent | |
threading.Thread.__init__(self) | |
self.daemon=True | |
def setCallback(self,callback): | |
self.callback = callback | |
def run(self): | |
idle_time_ms = int(self.idleTime*1000) | |
lastInputInfo = LASTINPUTINFO() | |
lastInputInfo.cbSize = ctypes.sizeof(lastInputInfo) | |
while True: | |
if not self.continueEvent.isSet(): | |
break | |
if not self.idleEvent.isSet(): | |
ctypes.windll.user32.GetLastInputInfo(ctypes.byref(lastInputInfo)) | |
elapsed = ctypes.windll.kernel32.GetTickCount() - lastInputInfo.dwTime | |
if elapsed>=idle_time_ms: | |
self.idleEvent.set() | |
if self.callback is not None: | |
self.callback() | |
else: | |
time.sleep(1) | |
class ActiveThread(threading.Thread): | |
""" | |
This class will clear the idle event every time the system is | |
considered active. | |
""" | |
def __init__(self,idleEvent,continueEvent): | |
self.callback = None | |
self.idleEvent = idleEvent | |
self.continueEvent = continueEvent | |
threading.Thread.__init__(self) | |
self.daemon=True | |
def setCallback(self,callback): | |
self.callback = callback | |
def run(self): | |
lastInputInfo = LASTINPUTINFO() | |
lastInputInfo.cbSize = ctypes.sizeof(lastInputInfo) | |
lasttime = None | |
while True: | |
if not self.continueEvent.isSet(): | |
break | |
if self.idleEvent.isSet(): | |
ctypes.windll.user32.GetLastInputInfo(ctypes.byref(lastInputInfo)) | |
if lasttime is None: lasttime = lastInputInfo.dwTime | |
if lasttime != lastInputInfo.dwTime: | |
lasttime = None | |
self.idleEvent.clear() | |
if self.callback is not None: | |
self.callback() | |
else: | |
time.sleep(1) | |
else: #platform != Windows | |
class IdleThread(threading.Thread): | |
""" | |
This class will raise an event every time the system is | |
considered Idle. | |
""" | |
def __init__(self,idleTime,idleEvent,continueEvent): | |
self.callback = None | |
self.idleTime = idleTime | |
self.idleEvent = idleEvent | |
self.continueEvent = continueEvent | |
threading.Thread.__init__(self) | |
self.daemon=True | |
def setCallback(self,callback): | |
self.callback = callback | |
def run(self): | |
while True: | |
if not self.continueEvent.isSet(): | |
break | |
if not self.idleEvent.isSet(): | |
#Todo: Determine how to tell if the system is idle | |
pass | |
class ActiveThread(threading.Thread): | |
""" | |
This class will clear the idle event every time the system is | |
considered active. | |
""" | |
def __init__(self,idleEvent,continueEvent): | |
self.callback = None | |
self.idleEvent = idleEvent | |
self.continueEvent = continueEvent | |
threading.Thread.__init__(self) | |
self.daemon=True | |
def setCallback(self,callback): | |
self.callback = callback | |
def run(self): | |
while True: | |
if not self.continueEvent.isSet(): | |
break | |
if self.idleEvent.isSet(): | |
#Todo: Determine how to tell if the system is no longer idle | |
pass | |
class IdleChecker: | |
def __init__(self,idle_time): | |
self.idleTime = idle_time | |
self.idleEvent = threading.Event() | |
self.continueEvent = threading.Event() | |
self.continueEvent.set() | |
self.activeThread = ActiveThread(self.idleEvent, self.continueEvent) | |
self.idleThread = IdleThread(self.idleTime,self.idleEvent, self.continueEvent) | |
self.idleThread.start() | |
self.activeThread.start() | |
def __del__(self): | |
self.stop() | |
def isActive(self): | |
return not self.isIdle() | |
def isIdle(self): | |
return self.idleEvent.isSet() | |
def setActiveCallback(self,callback): | |
self.activeThread.setCallback(callback) | |
def setIdleCallback(self,callback): | |
self.idleThread.setCallback(callback) | |
def stop(self): | |
self.continueEvent.clear() | |
if __name__ == '__main__': | |
def back(): | |
print "I am back!" | |
def gone(): | |
print "I am gone..." | |
idleChecker = IdleChecker(4) | |
idleChecker.setActiveCallback(back) | |
idleChecker.setIdleCallback(gone) | |
i = 0 | |
while True: | |
i = i + 1 | |
print i | |
time.sleep(1) | |
if idleChecker.isIdle(): print "yup... it's idle." | |
if i == 20: | |
break | |
idleChecker.stop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment