Skip to content

Instantly share code, notes, and snippets.

@tstone2077
Created February 23, 2011 08:03
Show Gist options
  • Save tstone2077/840156 to your computer and use it in GitHub Desktop.
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.
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